面试全部知识 您所在的位置:网站首页 redissearch elasticsearch 面试全部知识

面试全部知识

#面试全部知识| 来源: 网络整理| 查看: 265

一、阶段一、Java基础1、java跨平台的原理;1. JDK 和 JRE 、jvm有什么区别?2、面向对象的基本特征?3. 有了基本数据类型,为什么还需要包装类型?4、== 和 equals区别面试题5、String和StringBuilder和StringBuffer的区别?以及什么场景下使用StringBuilder什么场景使用StringBuffer?6.实现一个拷贝文件的工具类使用字节流还是字符流?7、讲一下什么是设计模式?常用的设计模式有哪些?8、final finally finalize区别?9.静态变量与实例变量、普通变量的区别10.重载和重写的区别?重载的方法能否根据返回类型进行区分?11.抽象类和接口的区别?12、两个对象的 hashCode() 为true,则 equals() 也一定为 true,对吗?13、如何将字符串反转?14.String常用的方法有哪些?15.Java中的IO流分为几种?16.BIO和NIO和AIO有什么区别?17.Files常用的方法有哪些?18.Java 中的 Math. round(-1. 5) 等于多少?19.String str=”i”与 String str=new String(“i”)一样吗?集合容器:1、讲一下java中的集合?2. Collection 和 Collections 有什么区别?3、讲一下ArrayList 与 LinkedList、HashSet 与 TreeSet、HashMap与HashTable与ConcurrentHashMap的区别?4. 如何决定使用 HashMap 还是 TreeMap?5. 说一下 HashMap 的实现原理?6. 说一下 HashSet 的实现原理?7. ArrayList 和 Vector 的区别是什么?8. Array 和 ArrayList 有何区别?9. 在 Queue 中 poll()和 remove()有什么区别?10. 哪些集合类是线程安全的?11. 迭代器 Iterator 是什么?12. Iterator 怎么使用?有什么特点?13. Iterator 和 ListIterator 有什么区别?14. 怎么确保一个集合不能被修改?15、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?16、 常见数据结构17、常见算法18.说一下查找二叉树的理解?AVL树(平衡树),红黑树的特点19、说一下B树和B+树的区别20、说一下数据结构的分类?21、说一下你理解的排序算法22、说一下你理解的查找算法23、.HASH算法的原理(Hahs表)24. Hash冲突的解决方案25、HashMap底层用到了那些数据结构,HashMap扩容机制?26、为什么要用到链表结构?27、为什么要用到红黑树?28.链表和红黑树在什么情况下转换的?29、HashMap在什么情况下扩容?HashMap如何扩容的?30.HashMap是如何Put一个元素的?32.什么是Hash冲突33、HashMap是如何解决Hash冲突的?34、手写一个冒泡排序(代码截图加上注释)35、手写一个二分查找(代码截图加上注释)public class SearchElement {36、ConcurrentHashMap原理?37、说一下ES用到了什么数据结构?多线程:1.讲一下线程的几种实现方式?启动方式?区分方式?2. 并行和并发有什么区别?3. 线程和进程的区别?4. 守护线程是什么?5. 创建线程有哪几种方式?6. 说一下 runnable 和 callable 有什么区别?7. 线程有哪些状态?8、 sleep() 和 wait() 有什么区别?9. notify()和 notifyAll()有什么区别?10. 线程的 run() 和 start() 有什么区别?11、创建线程池有哪几种方式?12、. 线程池都有哪些状态?13. 线程池中 submit() 和 execute() 方法有什么区别?14. 在 Java 程序中怎么保证多线程的运行安全?15、 多线程中 synchronized 锁实现原理以及升级的原理是什么?16. 什么是死锁?17 . 怎么防止死锁?18、 ThreadLocal 是什么?有哪些使用场景?19. 说一下 synchronized 底层实现原理?20、 synchronized 和 volatile 的区别是什么?21. synchronized 和 Lock 有什么区别?只不过是小程序发起请求只不过是小程需要小程序发起请求工种平台和开发为公司微信22. synchronized 和 ReentrantLock(可重入锁) 区别是什么?24、.悲观锁和乐观锁区别25. 说一下 atomic 的原理?26、int和Integer以及AtomicInteger的区别?27、Java线程池七个参数详解28. 常用的线程池有几种,分别是什么意思?29.线程池的原理执行流程

30、为什么要使用连接池,数据库连接池的原理

31、在ThreadPoolExecutor类中几个重要的方法反射1. 什么是反射?2、说说反射创建实例的几种方式?3、如何通过反射调用对象的方法?4. 什么是 Java 序列化?什么情况下需要序列化?5. 动态代理是什么?有哪些应用?6. 怎么实现动态代理?对象拷贝1. 为什么要使用克隆?2. 如何实现对象克隆?3. 深拷贝和浅拷贝区别是什么?异常1、 throw 和 throws 的区别?2、final、finally、finalize 有什么区别?3、 try-catch-finally 中哪个部分可以省略?4、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?5、常见的异常类有哪些?6、异常处理的方式7、项目中是否运用到全局异常?二、Web阶段1.preparedStatement和Statement的区别2、#与$的区别?4、session 和 cookie 是什么?有什么区别?Session与cookie的执行原理?5、 如果客户端禁止 cookie 能实现 session 还能用吗?6.请求转发和重定向的区别?7、get和post请求的区别8、servlet 和js、 JSP是什么?有什么区别?①Servlet:servlet的生命周期:servlet的三大职责:servlet与filter过滤器的区别②、JS (JavaScript);③、jsp (Java Server Pages):9、JSP的原理10、JSP 有哪些内置对象?作用分别是什么?11、jsp四大作用域的层级关系?四大作用域的生命周期?12、jQuery与script原生态区别;13、 spring mvc 和 struts 的区别是什么?14. 什么是 XSS 攻击,如何避免?15. 什么是 CSRF 攻击,如何避免?16、简单介绍数据三范式17、事务四个基本特性或ACID特性、及事务的传播机制、Mysql事务的隔离机制以及解决的问题、分布式事务解决方案?①、事务四个基本特性③、事务隔离机制以及解决的问题③、事务的隔离级别实现的原理?④、什么是分布式事务以及解决方案?(1)、什么是本地事务:(2)、什么是分布式事务:(3)、分布式事务运用场景:(4)、分布式事务产生的原因:2.1 数据库分库分表2.2 应用SOA化(5)、分布式事务的理论:CAP理论:BASE理论:(6)、如何选择CAP还是BASE:(7)、分布式事务解决的方案:常见方案:①、XA方案/两阶段提交②、三阶段提交(3PC)③、TCC方案补偿事务④、本地消费表⑤、消息事务最终一致性方案⑥、最大努力通知方案总结:(8) 、什么是分布式锁?(9)、分布式锁的解决方案与实现有哪些呢?1)、数据库解决方案思路:2)、基于redis缓存实现(放入redis共享锁): 使用redis的指令:通常使用setnx方法,incr方法等进行实现3).Zookeeper分布式锁:使用api生成临时节点实现锁!18、mysql数据库的最大连接数?19、说一下mysql分页?Oracle的分页20、简单说下你对jdbc的理解21、写一个简单的jdbc程序22、数据库连接池作用23、文件上传三要素:24、一个select语句的关键字的定义顺序是怎么样的?25.一个select语句中关键字是按照什么顺序执行的?26.Mybatis的Mapper接口为什么可以@Autowire直接注入27.在Mybatis中,mapper.xml有一个sql为: select from user ,如何在不修改sql的基础上在sql后面加上 where id = 1 ?28.MyBatis的动态SQL标签有哪些?29、Mybatis的mapper如何传递多个参数①、dao按照获取的顺序进行获取、②、打注解@param、③、封装成一个map进行传递

30、嵌套子查询和JOIN有什么区别?31、在ResultMap中多对一关联对象查询用什么?一对多关联查询用什么?数据库:一、Mysql1、MySQL的优化2、MySQL的执行流程3、MySQL数据库的常见的索引有几种实现方式?4、MySQL数据库的常见优化5、MySQL的行锁和表锁6、MySQL的主从配置7、MySQL如何实现读写分离8、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?9、如何获取当前数据库版本?10、char 和 varchar 的区别是什么?11、float 和 double 的区别是什么?12、MySQL 的内连接、左连接、右连接有什么区别?13、怎么验证 MySQL 的索引是否满足需求?14、说一下 MySQL 常用的引擎?15、MySQL 问题排查都有哪些手段?二、Redis1、Redis 是什么,使用场景、有什摸功能?2、Redis 的支持数据类型?3、Redis持久化方式:RDB、AOF文件存储的方式;4.redis优化-.淘汰策略5、Redis分布式项目中央缓存的问题6、Redis 相比 Memcached 有哪些优势?7、Memcache 与 Redis 的区别都有哪些?8、Redis 是单进程单线程的?9、为什么redis 需要把所有数据放到内存中?10、Redis 的同步机制了解么?11、是否使用过 Redis 集群,集群的原理是什么?12、Redis 集群方案什么情况下会导致整个集群不可用?13、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?14、Jedis 与 Redisson 对比有什么优缺点?15、说说 Redis 哈希槽的概念?16、Redis 集群的主从复制模型是怎样的?17、Redis 集群会有写操作丢失吗?为什么?18、Redis 集群之间是如何复制的?19、Redis 集群如何选择数据库?20、怎么测试 Redis 的连通性?21、怎么理解② Redis 事务?22、Redis 事务相关的命令有哪几个?23、Redis key 的过期时间和永久有效分别怎么设置?24、Redis 如何做内存优化?25、Redis 回收进程如何工作的?26、都有哪些办法可以降低 Redis 的内存使用情况呢?27、Redis 的内存用完了会发生什么?28、一个 Redis 实例最多能存放多少的 keys?List、Set、29、MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如 何保证 redis 中的数据都是热点数据?30、如果有大量的 key 需要设置同一时间过期,一般需要注意31、使用过 Redis 做异步队列么,你是怎么用的?32、Redis为什么是单线程的而不是多线程的?从cpu的角度来看,单线程和多线程有什么性能的区别?为什么单线程也能实现这么高的性能?33、有没有做Redis的集群?有哪几种方式,Redis的集群最少要有多少个节点?如果其中一个节点挂掉会怎样?如果只有两个主节点Redis能不能跑起来?34、Redis分布式锁,解决的是分布式的线程问题,Redis分布式锁的实现思路,怎样做到线程安全?35、Redis 实现分布式锁原理流程?36、Redis 分布式锁有什么缺陷?37、Redisson(redis集群的分布式锁):三、主流框架阶段1.Mybatis、Spring、SpringMVC,SpringBoot,SpringCloud的区别?①、MyBatis②、spring③、SpringMVC:springMVC执行流程——面试题④、springBoot⑤、spring cloud2、介绍spring框架的组成3、说一下你对IOC的理解4.说一下你对AOP的理解4、如何自定义一个AOP,实现切面?6、BeanFactory和ApplicationContext有什么区别,Spring的Bean懒加载和非懒加载有什么区别7、Spring的Bean被指定为singleton(生狗疼)以及proto type有什么区别? spring 支持几种 bean 的作用域?8、Spring的依赖注入方式以及实现的有哪些?9、Spring的Bean的创建方式以及生命周期、bean的自动装配原理?(掌握)创建方式:Bean生命周期:Spring Bean的自动装配原理:10、springboot配置事务:11、有哪些方式可以注册一个Bean到容器中12. 将一个类声明为Spring的Bean的注解有哪些?13. Spring的IOC启动原理14、Spring是如何管理事务的?15、Spring事务的回滚机制:16. Spring用到了哪些设计模式17、RequestMapping 和 GetMapping区别?18.SpringMVC怎么样设定重定向和转发的19.SpringMVC如何对时间格式的参数进行格式化?有哪些方式?20.SpringMVC常用的注解有哪些 ?21.如何定义SpringMVC的拦截器22、过滤器和拦截器的区别?23、HandlerInterceptor和HandlerInterceptorAdapter的区别?24.SpringMVC的执行原理25.SpringMVC的Controller是单例还是多例,有没有并发安全问题,如何解决?26、SpringBoot有哪些优点?27、SpringBoot如何做全局异常处理?28、SpringBoot如何读取配置文件中的配置项?29、@SpringBootApplication标签的组成30、.SpringBoot是如何整合SpringMVC的?SpringBoot是如何整合DataSource的?31.SpringBoot的启动流程32.SpringBoot和SpringCloud的区别?33、SpringCloud常用组件和作用?34.Eureka心跳和服务剔除机制是什么35.Eureka的服务注册与发现的工作流程36.对于CAP理论,Eureka选择的是AP还是CP?它保证了一致性还是可用性?37.说下Ribbon和Feign的区别呢?38.一个请求过来,在你们的微服务项目中经过哪些流程?39、如何实现Eureka的高可用集群?40、Hystrix的限流有几种方式,有什么区别?41.Hystrix的熔断有几种状态?这几种状态是怎么变换的?42、服务A使用ribbon调用服务B,Ribbon是如何工作的?43、为什么Feign的接口可以直接注入进来用?44、Ribbon的负载均衡算法有哪些?45、Zuul有哪几类Filter,他们的执行顺序是怎么样的?46. 在Zuul中做登录检查如何实现?47、EurekaClient拉取注册表&心跳续约用到了什么技术来实现?48、Springcloud分布式SpringSecurity项目授权、鉴权流程一、微服务授权认证方式:1、微服务授权常见方案二、微服务分布式项目采取:三、微服务项目认证授权怎么实现的?SpringSecurity认证流程四、常见的权限框架有关于项目一、单体项目:(1)、概念1 前后端分离的理解2 前端怎么独立开发?3 swagger是什么?4 交互方式5 后端如何进行接口测试?(2)、Redis1 为什么使用redis?2 redis的持久化机制。3 redis支持的数据类型。(3)、注册1 注册是怎么做的?2 密码是怎么处理的?(4)、登录1 用户和管理员登录是分开写的吗?2 登录这块的表设计是怎么样的?3 怎么判断用户是否登录?4 前端发起的所有的请求都会被拦截吗?5 是如何让所有的请求都携带token的?二、微服务项目:1、你们项目是如何做服务降级的?2、分布式项目是如何保证接口的幂等性的?3、用过redis吗?为什么要用?怎么用4、 用过ES没有?哪儿用的?为什么要用?怎么用?扩展(为什么用。详细解释)6、有没有做过页面静态化?为什么要使用?怎么使用6、有没有做做过数据库相关的优化?在哪儿做?为什么要做7、 有没有用过对象存储(分布式文件系统)?哪儿用?为什么要用?8、你的商城项目用户量多大?你觉得用分布式架构合理吗?9、你这个商城用了多少个数据库?10、你们怎么分库分表的?11、订单你处理过的并发量有多大?12、第三方支付怎么做的13、你项目中是怎么实现单点登录的?秒杀总结:一、商城商品秒杀三大难点二、秒杀商品流程:三、秒杀业务实现流程四、秒杀功能的优化(1)、前端优化(2)、后端优化ES(ElasticSearch)1、谈谈你对ElasticSearch的理解?2、ES(ElasticSearch)优点3、ES(ElasticSearch)相关概念4.ElasticSearch__CRUD5、ES(ElasticSearch)全文搜索的两个核心、6.ES(ElasticSearch)全文搜索创建索引大致原理倒排索引是什么?7、ES(ElasticSearch)全文搜索哪些要建索引、要分词、不分词、哪些要存储到数据区?8、ES(ElasticSearch)查询条件?9、ElasticSearch使用的是query还是filter, 两者之间有什么区别10、为什么不使用MySQL查询,而要用ES呢?11、 Lucene和ES的区别12、MySQL 数据如何同步到 ES 中方案 1:监听 MySQL 的 Binlog,分析 Binlog 将数据同步到 ES 集群中。优点:业务与 ES 数据耦合度低,业务逻辑中不需要关心 ES 数据的写入;缺点:Binlog 模式只能使用 ROW 模式,且引入了新的同步服务,增加了开发量以及维护成本,也增大了 ES 同步的风险。方案 2:直接通过 ES的API 将数据写入到 ES 集群中。13、在并发情况下,Elasticsearch 如果保证读写一致?14、ElasticSearch的算法优化RabbitMQ1、RabbitMQ 的使用场景有哪些?1、rabbitMQ执行的原理:2、消息队列的基本模型3、RabbitMQ什么情况下会出现消息丢失,如何解决4、RabbitMQ如何防止重复消费消息 :幂等5、RabbitMQ的交换机分为几类?有什么区别6、.SpringBoot整合MQ的大致步骤8、 RabbitMQ 有哪些重要的角色?9. RabbitMQ 有哪些重要的组件?10、 RabbitMQ要保证消息持久化成功的条件有哪些?11、RabbitMQ 怎么保证消息的稳定性?12、RabbitMQ 怎么避免消息丢失?13、RabbitMQ 持久化有什么缺点?14. RabbitMQ 中 vhost 的作用是什么?15、RabbitMQ 怎么实现延迟消息队列、使用场景?16、RabbitMQ 集群有什么用?17、 RabbitMQ 节点的类型有哪些?18、RabbitMQ 集群搭建需要注意哪些问题?19、RabbitMQ 每个节点是其他节点的完整拷贝吗?为什么?20、RabbitMQ 集群中唯一一个磁盘节点崩溃了会发生什么情况?21、 RabbitMQ 对集群节点停止顺序有要求吗?Zookeeper1. zookeeper 是什么?2.Zookeeper实现分布式锁的原理?3. zookeeper 都有哪些功能?4. zookeeper 有几种部署模式?5. zookeeper 怎么保证主从节点的状态同步?6. 集群中为什么要有主节点?7. 集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?8. 说一下 zookeeper 的通知机制?JVM1. 说一下 JVM 的主要组成部分?及其作用?2. 说一下 JVM 运行时数据区?3. 说一下堆栈的区别?4. 队列和栈是什么?有什么区别?5. 什么是双亲委派模型?6. 说一下类装载的执行过程?7. 怎么判断对象是否可以被回收?8. Java 中都有哪些引用类型?9. 说一下 JVM 有哪些垃圾回收算法?10. 说一下 JVM 有哪些垃圾回收器?11. 详细介绍一下 CMS 垃圾回收器?12. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?13. 简述分代垃圾回收器是怎么工作的?14. 说一下 JVM 调优的工具?15. 常用的 JVM 调优的参数都有哪些?

一、阶段一、

Java基础

1、java跨平台的原理;

在不同的操作系统上安装jvm虚拟机,避免各个系统之间的差异后,提供统一的接口,然后就可以在各个操作系统上运行java代码。

1. JDK 和 JRE 、jvm有什么区别?

· JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。· JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。JDK包含jvm

2、面向对象的基本特征?

封装:将对象封装成一个高度自治和相对封闭的个体,为了保证隐私和安全性,步骤:类要public修饰,私有化成员变量,提供公共无参构造方法,提供合理的getXxx()和setXxx(数据类型 变量名)方法继承:将一些共有属性和方法抽取出来,单独成为一个类,为其他的类可以继承类,就可以获取共有的属性。作用:代码复用,提高开发效率和代码的拓展性多态:同一个行为具有多个不同表现形式或形态的能力。编译时和运行时类型不一致的情况。抽象:找出一些事物的相似和共性之处,然后将这些事物归为一个类。

3. 有了基本数据类型,为什么还需要包装类型?

因为java是一个面向对象的语言,然而基本数据类型不具备面向对象思想的特点,当我们把基本数据类型包装成包装类型之后,它就具有了面向对象的特性。

4、== 和 equals区别面试题

==: 比较基本数据类型: 比较的就是值是否相等;比较引用数据类型: 比较的是对象的地址是否相等equals 只能用于引用类型根据实际业务比较两个对象是否相等。默认是不重写是==比较。在实际开发中,我们一般比较对象都是通过对象的属性值进行比较(一般比较对象的地址没有多大用处),所以我们会覆写Object中的此方法,把自己的判断机制写在方法里面;

5、String和StringBuilder和StringBuffer的区别?以及什么场景下使用StringBuilder什么场景使用StringBuffer?

他们都是进行子字符串操作的类,主要区别在于:String是不可变的(字符串常量),string底层由是final修饰的不可变的char数组,由于不可变,进行字符串操作每次都会生成新的 String 对象,然后将指针指向新的 String 对象,StringBuffer,StringBuilder没有被final修饰,即可变,所以StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 字符串变量 StringBuffer:字符串变量,(里面的方法都是使用synchronized修饰,没有线程安全问题,但执行效率就低了点)。适用多线程下在字符缓冲区进行大量操作的情况。StringBulider:字符串变量,线程不安全,效率高。适用于单线程下在字符缓冲区进行大量操作

6.实现一个拷贝文件的工具类使用字节流还是字符流?

我们拷贝的文件不确定是只包含字符流,有可以能有字节流(图片、声音、图像等),为考虑到通用性,要使用字节流。

7、讲一下什么是设计模式?常用的设计模式有哪些?

设计模式就是经过前人无数次的实践总结出的,设计过程中可以反复使用的、可以解决特定问题的设计方法。

①单例模式 提供单个实例 (饱汉模式、饥汉模式)

(1)、懒汉(线程不安全)

步骤:1、私有化构造方法 2、定义静态属性 不赋值(定义该类的数据类型) 3、对外提供获取实例的静态方法(必须有static修饰)4、提供返回实例的方法(2)、饿汉 1、私有化构造方法 2、定义静态属性 不赋值(定义该类的数据类型) 3、对外提供获取实例的静态方法(必须有static修饰)4、返回实例的方法(3)、枚举

单例模式优点: 1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例 2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。 3.提供了对唯一实例的受控访问。 4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。 5.允许可变数目的实例。 6.避免对共享资源的多重占用。 单例模式缺点: 1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。 2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。 3.单例类的职责过重,在一定程度上违背了“单一职责原则”。 4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

单例模式使用注意事项: 1.使用时不能用反射模式创建单例,否则会实例化一个新的对象 2.使用懒单例模式时注意线程安全问题 3.单例模式和懒单例模式构造方法都是私有的,因而是不能被继承的,有些单例模式可以被继承(如登记式模式)

单例模式适用场景: 单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如: 1.需要频繁实例化然后销毁的对象。 2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。 3.有状态的工具类对象。 4.频繁访问数据库或文件的对象。

以下都是单例模式的经典使用场景: 1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。 2.控制资源的情况下,方便资源之间的互相通信。如线程池等。 应用场景举例: 1.外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件 2. Windows的TaskManager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~ 3. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

②工厂模式:Spring IOC就是使用了工厂模式.对象的创建交给一个工厂去创建。就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。实现方式:a) 抽象产品类(也可以是接口)b) 多个具体的产品类c) 工厂类(包括创建a的实例的方法)

③代理模式:Spring AOP就是使用的动态代理。代理模式:一)静态代理实现方式:a)为真实类和代理类提供的公共接口或抽象类。(租房)b)真实类,具体实现逻辑,实现或继承a。(房主向外租房)c) 代理类,实现或继承a,有对b的引用,调用真实类的具体实现。(中介)d)客户端,调用代理类实现对真实类的调用。(租客租房)

二)动态代理(1)、jdk动态代理使用的局限性: 通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实 现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方 方式实现动态代理。(2)、cglib动态代理 (没有接口实现)

实现方式:a)公共的接口(必须是接口,因为Proxy类的newproxyinstance方法的第二参数必须是个接口类型的Class)b)多个真实类,具体实现的业务逻辑。c) 代理类,实现InvocationHandler接口,提供Object成员变量,和Set方法,便于客户端切换。d)客户端,获得代理类的实例,为object实例赋值,调用Proxy.newproxyinstance方法在程序运行时生成继承公共接口的实例,调用相应方法,此时方法的执行由代理类实现的Invoke方法接管。

④ 观察者模式:观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。实现方式:a)角色抽象类(提供对观察者的添加,删除和通知功能)。b)角色具体类,实现a,维护一个c的集合(对角色抽象类的实现)。c) 观察者抽象类(被角色通知后实现的方法)。d)观察者实现类,实现c(多个)。注:JDK提供了对观察者模式的支持,使用Observable类和Observer接口

⑤适配器模式:适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。1. 类适配器(子类继承方式)实现方式:a) 目标抽象角色(定义客户要用的接口)b) 适配器(实现a继承c,作为一个转换器被客户调用)c) 待适配器(真正需要被调用的)d) 客户端(借用a的实例调用c的方法)

⑥装饰模式:实现方式:a) 抽象的被装饰角色(所有的角色都要直接或间接的实现本角色)b) 具体的被装饰角色,实现或继承a (被功能扩展的角色)c) 装饰角色,实现或继承a (本类有对a的引用,所有的具体装饰角色都需要继承这个角色)d) 多个具体修饰角色,继承c(对被装饰角色的功能扩展,可以任意搭配使用)

8、final finally finalize区别?

Final:可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。Finally:一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。Finalize:是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。

9.静态变量与实例变量、普通变量的区别

静态变量:静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。实例变量:每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量

10.重载和重写的区别?重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于重载实现的是编译时的多态性,而重写实现的是运行时的多态性。重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。

11.抽象类和接口的区别?

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。相同点:①接口和抽象类都不能实例化②都位于继承的顶端,用于被其他实现或继承③都包含抽象方法,其子类都必须覆写这些抽象方法

不同点:抽象类、接口从声明、实现方式、构造器、访问修饰符、继承的特点、成员变量字段的修饰。

实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。构造函数:抽象类可以有构造函数;接口不能有。实现数量:类可以实现很多个接口;但是只能继承一个抽象类。访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

12、两个对象的 hashCode() 为true,则 equals() 也一定为 true,对吗?

然而哈希值相等,并不一定能得出键值对相等。

13、如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

14.String常用的方法有哪些?

· replace():字符串替换。· trim():去除字符串两端空白。· split():分割字符串,返回一个分割后的字符串数组。· getBytes():返回字符串的 byte 类型数组。· length():返回字符串长度。· toLowerCase():将字符串转成小写字母。· toUpperCase():将字符串转成大写字符。· substring():截取字符串。equals():字符串比较。· indexOf():返回指定字符的索引。· charAt():返回指定索引处的字符。

15.Java中的IO流分为几种?

按功能来分:输入流(input)输出流(output)。按类型来分:字节流字符流字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

16.BIO和NIO和AIO有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

17.Files常用的方法有哪些?

· Files. exists():检测文件路径是否存在。· Files. createFile():创建文件。· Files. createDirectory():创建文件夹。· Files. delete():删除一个文件或目录。· Files. copy():复制文件。· Files. move():移动文件。· Files. size():查看文件个数。· Files. read():读取文件。· Files. write():写入文件。

18.Java 中的 Math. round(-1. 5) 等于多少?

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

19.String str=”i”与 String str=new String(“i”)一样吗?

不一样,因为内存的分配方式不一样。String str=”i”的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

集合容器:

1、讲一下java中的集合?

Java中的集合分为value,key—vale(Conllection Map)两种。存储值有分为List 和Set.List:是有序的,可以重复的、线程不安全。Set:是无序的,不可以重复的、线程不安全。根据equals和hashcode判断,也就是如果,一个对象要存储在Set中,必须重写equals和hashCode方法。存储key-value的为map.

2. Collection 和 Collections 有什么区别?

Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法: Collections. sort(list)。

3、讲一下ArrayList 与 LinkedList、HashSet 与 TreeSet、HashMap与HashTable与ConcurrentHashMap的区别?

ArrayList 与 LinkedList?相同点:都是list接口 的实现类 都可存放任意类型任意多个数据 都是线程不安全 都是有序(添加顺序与输出顺序一致)ArrayList LinkedList 遍历方式相同: for循环 foreach 迭代器不同点:ArrayList底层基于数组实现: 因为底层基于数组实现 数据具有索引 因此可以根据索引直接定位到数据 因此查询和修改较快,而添加和删除较慢 因为添加涉及到新建数组 的创建以及数据的拷贝 此时消耗性能和内存较多 LinkedList底层基于双向链表实现 因为底层基于链表实现,不用去判断是否需要扩容或者数据的拷贝,此时添加、删除的速度较快,当查询、修改的时候 需要遍历整个链表 速度相对较慢HashSet 与 TreeSet区别?相同点:都是set接口实现类 都可以存放任意类型任意多个数据 都是无序不可重复 都线程不安全 不同点:HashSet LinkedHashSet能够存储任意类型任意多个数据 包括null HashSet底层基于HashMap实现 添加数据是 主要通过hashCode和equals方法去重(是根据hashcode与equals方法共同决定的先去用hashcode判断是否相等,然后再用equals方法进行比较是否相同,如果hashcode方法判断不相等时,就不会调用equals方法进行比较。)

TreeSet底层基于TreeMap实现 添加数据时 主要通过自然排序或者定制排序去重 TreeSet任意一种类型多个数据 不包括null 只能够同时存储同一种类型的数据 自然排序:实体类实现Comparable接口 定制排序:实现Comparator 将比较器交给集合容器HashSet 与 TreeSet遍历方式:foreach 迭代器HashMap与HashTable与ConcurrentHashMap区别?相同点:都是map接口的实现类 都是以键值对形式存储值 key不能重复 value可重复 遍历方式两种获取keyset或者entryset不同点:HashMap ( jdk1.7及其以前 底层基于数组+链表实现, jdk1.8以后 底层基于数组+链表实现+红黑树)线程不安全 可以使用null作为键或者值 效率最高 Hashtable 同步方法保证线程安全 不可以使用null作为键或者值效率最低。ConcurrentHashMap 同步代码块保证线程安全 效率较高 不 可以使用null作为键或者值。我想线程安全但是我又想效率高?通过把整个Map分为N个Segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。

4. 如何决定使用 HashMap 还是 TreeMap?

对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。

5. 说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。

6. 说一下 HashSet 的实现原理?

HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。

7. ArrayList 和 Vector 的区别是什么? 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。性能:ArrayList 在性能方面要优于 Vector。扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。 8. Array 和 ArrayList 有何区别?· Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。· Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。· Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。 9. 在 Queue 中 poll()和 remove()有什么区别?· 相同点:都是返回第一个元素,并在队列中删除返回的对象。· 不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。代码示例:Queue queue = new LinkedList();queue. offer(“string”); // addSystem. out. println(queue. poll());System. out. println(queue. remove());System. out. println(queue. size()); 10. 哪些集合类是线程安全的?Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap。 11. 迭代器 Iterator 是什么?Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。 12. Iterator 怎么使用?有什么特点?Iterator 使用代码如下:List list = new ArrayList();Iterator it = list. iterator();while(it. hasNext()){ String obj = it. next(); System. out. println(obj);}Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。 13. Iterator 和 ListIterator 有什么区别?· Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。· Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。· ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。 14. 怎么确保一个集合不能被修改?可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。示例代码如下:List list = new ArrayList();list. add(“x”);Collection clist = Collections. unmodifiableCollection(list);clist. add(“y”); // 运行时此行报错System. out. println(list. size()); 15、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。

TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。

Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;

第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)

16、 常见数据结构

2.1 什么是数据结构存数据及数据之间关系集合。2.2 逻辑结构1)集合2)线性结构3)树状结构4)图形结构 2.3 物理结构1)顺序存储 - java用数组2)链式存储3)索引存储4)hash存储 2.4 常用数据结构 1)集合 HashSet2)线性结构数组 线性表-顺序表(ArrayList)链表(LinkedList) 栈:FILO 顺序栈链栈 队列:FIFO 顺序队列链式队列 串:定长String 堆StringBuilder StringBuffer3)树状结构二叉树:二叉排序树。。。红黑树。。。 多叉树:B树 B-树 b+树(innodb)。。。。

17、常见算法

3.1 什么是算法解决问题步骤有限集合。在java中就是方法3.2 评价算法是否高效时间复杂度:时间频度,从理论上看它执行多少语句 o(1) o(n) o(2n) o(N平方)空间复杂度:是否有额外空间空间换取时间3.3 常见算法 hash(散列)算法 递归递归:自己调用自己,有出口 递归优化-数据库查询排序:java Arrays.sort Collections.sort Compartor(小于返回负数,大于返回正数)还要很多排序算法冒泡。。。查找二分查找:排序数据

18.说一下查找二叉树的理解?AVL树(平衡树),红黑树的特点

理解:每个节点只有两个分叉,左边分叉的数据比节点数据小,右边的数据更大。AVL树(平衡树):左右两边的高度差不能相差一,查询效率高()红黑树:也是一个平衡树,增删改快,父节点为黑色,下面每层就是黑色红色交替,最底下节点为红色 会自动在拼接两个黑色的节点为null

19、说一下B树和B+树的区别

B树的节点存储数据,B+树存储数据的地址(一般只有两层)B+树相对于B树的优势

n 每个节点存储更多的KEY,树的高度更低,时间复杂度越小,查询越快n 数据在叶子节点,每次查询都要查询到叶子节点,查询速度比较稳定n 叶子节点构成构成了链表结构,方便区间查询和排序

Mysql为什么使用B+树: 以最小的IO找到更多的记录数,如果是B树,由于每个节点要存储Key和Value(数据) ,那么每个节点能存储的Key是很少的,而B+树每个节点只存储Key,它可以存储更多的Key, 每个节点存储的Key越多,路数越多,节点就越少,需要耗时的IO就越少,查找性能就越高,且B+树的叶子节点是有序的,形成链表,方便区间查询和排序

20、说一下数据结构的分类?

21、说一下你理解的排序算法

22、说一下你理解的查找算法

l 顺序查找 无序数据查找,从前往后查找l 二分查找 有序数据中进行查找l 插值查找l 斐波那契查找l 树表查找l 分块查找l 哈希查找

23、.HASH算法的原理(Hahs表)

基于哈希表:根据结点的关键码值来确定其存储地址:

24. Hash冲突的解决方案

n 拉链法/链地址法:把Hash碰撞的元素指向一个链表n 开放寻址法:当 p=h(key)出现冲突,就以p为基础产生另一个Hash,如:p1=h(p),直到不冲突了把元素放在该位置n 再散列法:准备若干个hash函数,如果使用第一个hash函数发生了冲突,就使用第二个hash函数,第二个也冲突,使用第三个n 建立公共溢出区:把Hash表分为基本表和溢出表,把和基本表冲突的元素移到溢出表

25、HashMap底层用到了那些数据结构,HashMap扩容机制?

1.用到了数组,链表,红黑树结构。

HashMap扩容机制1.数组长度是16,每个元素都是key-value结构,元素存储到%75(0.75负载因子)进行 2倍扩容。2.存储元素的算法是 hash(key) % 16 根据key进行hash计算得到的值来对数组长度16 取模,余数作为元素在数组中的存储索引位置。3链表为了解决Hash冲突 , 不同的key进行 hash计算可能hash值一样,那么技术出来的存储索引位置也一样,这叫hash冲突,HashMap使用链表的方式来解决Hash冲突,就是在当前索引位置的元素上向下拖一个链表。4.红黑树是为了提高查询速度了,因为链表过长,查询速度会很慢,红黑树能提高查询速度,当链表长度达到 8 编程红黑树,当链表长度小于 6 编程链表。

26、为什么要用到链表结构?

链表为了解决Hash冲突 , 不同的key进行 hash计算可能hash值一样,那么技术出来的存储索引位置也一样,这叫hash冲突,HashMap使用链表的方式来解决Hash冲突,就是在当前索引位置的元素上向下拖一个链表。

27、为什么要用到红黑树?

红黑树是为了提高查询速度了,因为链表过长,查询速度会很慢,红黑树能提高查询速度,当链表长度达到 8 编程红黑树,当链表长度小于 6 编程链表。

28.链表和红黑树在什么情况下转换的?

当链表长度达到 8 编程转化为红黑树,当链表长度小于 6 转化为编程链表。

29、HashMap在什么情况下扩容?HashMap如何扩容的?

元素存储到%75(0.75负载因子)进行 2倍扩容,位运算进行左移位。

30.HashMap是如何Put一个元素的?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据存储元素的算法是 hash值(key) % 16 根据key进行hash计算得到的值来对数组长度16 取模,余数作为元素在数组中的存储索引位置。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。**31.HashMap是如何Get一个元素的?与put相反

32.什么是Hash冲突

Hash冲突是存储两个不同的值而计算出了相同的Hash值,即两个数据在Hash表中计算出同一个下标,这种情况叫Hash冲突

33、HashMap是如何解决Hash冲突的?

n 拉链法/链地址法:把Hash碰撞的元素指向一个链表

34、手写一个冒泡排序(代码截图加上注释)

public static void main(String[] args) {

int x[]={7,345,456,2,36,36,798,3}; //定义一个要排序的数组 int test=0; //定义一个虚拟的数字

for (int i = 0; i < x.length-1; i++) {//每次都要比较完一个数直至到右边,所以-1 for (int j = 0; j < x.length-1-i; j++) {//每次都要比较完一轮数据,所以-i if (x[j]>x[j+1]) { //如果在比较的时候这个数比后一个的数更大 test=x[j]; //定义的虚拟数给它赋值为x[j] x[j]=x[j+1]; //给x数组的x[j]这个位置赋值为后一个更小的数 x[j+1]=test; //给x数组的x[j+1]这个位置赋值为前一个更大的数} } } for (int i = 0; i < x.length; i++) { System.out.print(x[i]+”,”);//打印出x[i]数组} }

35、手写一个二分查找(代码截图加上注释)public class SearchElement {

public static void main(String[] args) {//System.out.println(“hello”);int[] array = {1,2,3,4,5,6,7,8};int index = searchElement(array,0,7,100);int index2 = searchElement2(array,6);System.out.println(index2);}

//二分查找 递归public static int searchElement(int array[], int low, int high, int target) {if (low > high) return -1;int mid = (low + high) / 2;if (array[mid] < target)return searchElement(array, mid + 1, high, target);if (array[mid]> target)return searchElement(array,low,mid-1,target);return mid;}

//二分查找 不用递归public static int searchElement2(int[] array,int target){int low = 0;int high = array.length-1;while(low target){high = mid-1;}else if (array[mid] 等待队列 => 非核心线程 => 拒绝策略

第一、如果有空闲的核心线程直接使用,没有空闲的核心线程并且线程数量未达到corePoolSize(线程池核心线程大小),则用一个核心线程执行任务

第二、核心线程数量达到了corePoolSize,则将任务移入队,列等待空闲核心线程将其取出去执行(通过getTask方法从阻塞队列中获取等待的任务,如果队列中没有任务,getTask方法会被阻塞并挂起,不会占用cpu资源,整个getTask操作在自旋下完成),如果队列已满,新建普通线程(非核心线程)执行任务,空闲下来以后,非核心线程会按照时间策略进行销毁

第三、队列已满,核心线程、普通线程、队列总线程数又达到了maximumPoolSize(线程池最大线程数量)最大线程数,就会执行任务拒绝策略。

30、为什么要使用连接池,数据库连接池的原理

1、为什么用线程池?顾名思义,就是装与数据库连接对象的容器,可以极大的提升咱们操作数据库的性能,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;线程池可以看做是管理了N个线程的池子,和连接池类似。线程池的作用主要有:l 控制并发数量:线程并发数量过多,抢占系统资源从而导致阻塞,线程池可以限制线程的数量。l 线程的复用:创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率和速度l 管理线程的生命周期:对线程进行一些简单的管理,创建,销毁等

2、连接池的工作原理主要由三部分组成,分别为

连接池的建立、连接池中连接的使用管理、连接池的关闭①、第一、连接池的建立。一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。

Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。

②、第二、连接池的管理。连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:

当客户请求数据库连接时,

1)如果池中有空闲连接可用,返回该连接。2)如果没有空闲连接,池中连接都已用完,创建一个新连接添加到池中。3)如果池中连接已达到最大连接数,请求按设定的最大等待时间进入等待队列直到有空闲连接可用。4)如果超出最大等待时间,则抛出异常给客户。当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。

该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。

如果连接长时间空闲,或检测到与服务器的连接已断开,连接池管理器也会将该连接从池中移除。

③、第三、连接池的关闭。当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。

连接池需要注意的点1、并发问题为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。synchronized(java) lock(C#)关键字即可确保线程是同步的。

2、事务处理,保证事务具有原子性我们知道,,此时要求对数据库的操作符合“ALL-OR-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

我们知道当2个线程共用一个连接Connection对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使Connection类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有2个线程都在进行事务操作而引起的。

为此我们可以使用每一个事务独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性。

3、连接池的分配与释放

连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

对于连接的管理可使用一个List。即把已经创建的连接都放入List中去统一管理。每当用户请求一个连接时,系统检查这个List中有没有可以分配的连接。如果有就把那个最合适的连接分配给他,如果没有就抛出一个异常给用户。

4、连接池的配置与维护连接池中到底应该放置多少连接,才能使系统的性能最佳?

系统可采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接。

31、在ThreadPoolExecutor类中几个重要的方法

l Execute :方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。l Submit :方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,实际上它还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。l Shutdown :不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。l shutdownNow :立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。l isTerminated:调用ExecutorService.shutdown方法的时候,线程池不再接收任何新任务,但此时线程池并不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。在调用shutdown方法后我们可以在一个死循环里面用isTerminated方法判断是否线程池中的所有线程已经执行完毕,如果子线程都结束了,我们就可以做关闭流等后续操作了。

反射

1. 什么是反射?

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

2、说说反射创建实例的几种方式?

方式一:类名.class 得到这个类的字节码对象 不对类中的内容进行初始化操作

方式二:对象名 .getclass 得到类的字节码对象 对这个类的静态、非静态、构造方法进行初始化的操作。

方式三:class.forname 得到这个类的字节码对象 但是会对这个类的静态模块进行初始化的加载

3、如何通过反射调用对象的方法?

(1)、得到该对象所对应的Class对象(2)、通过该Class对象得到该类的构造方法所对应的Constructor对象(3)、通过该Constructor对象的newInstance方法得到该类的一个实例(对象)(4)、通过该Class对象得到该方法所对应的Method对象(5)、通过该Method对象的invoke方法进行调用

4. 什么是 Java 序列化?什么情况下需要序列化?

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。以下情况需要使用 Java 序列化:· 想把的内存中的对象状态保存到一个文件中或者数据库中时候;· 想用套接字在网络上传送对象的时候;· 想通过RMI(远程方法调用)传输对象的时候。

5. 动态代理是什么?有哪些应用?

动态代理是运行时动态生成代理类。动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。

6. 怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。③代理模式:Spring AOP就是使用的动态代理。代理模式:一)静态代理实现方式:a)为真实类和代理类提供的公共接口或抽象类。(租房)b)真实类,具体实现逻辑,实现或继承a。(房主向外租房)c) 代理类,实现或继承a,有对b的引用,调用真实类的具体实现。(中介)d)客户端,调用代理类实现对真实类的调用。(租客租房)

动态代理(1)、jdk动态代理使用的局限性: 通过反射类Proxy和InvocationHandler回调接口实现的jdk动态代理,要求委托类必须实 现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方 方式实现动态代理。(2)、cglib动态代理(没有接口实现)

实现方式:a)公共的接口(必须是接口,因为Proxy类的newproxyinstance方法的第二参数必须是个接口类型的Class)b)多个真实类,具体实现的业务逻辑。c) 代理类,实现InvocationHandler接口,提供Object成员变量,和Set方法,便于客户端切换。d)客户端,获得代理类的实例,为object实例赋值,调用Proxy.newproxyinstance方法在程序运行时生成继承公共接口的实例,调用相应方法,此时方法的执行由代理类实现的Invoke方法接管。

对象拷贝

1. 为什么要使用克隆?

克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。

2. 如何实现对象克隆?

· 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。· 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

3. 深拷贝和浅拷贝区别是什么?

· 浅克隆:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。· 深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将复制。

异常

1、 throw 和 throws 的区别?

throw:是真实抛出一个异常。throws:是声明可能会抛出一个异常。

2、final、finally、finalize 有什么区别?

final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。finalize: 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

3、 try-catch-finally 中哪个部分可以省略?

try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。

4、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,才会执行。

5、常见的异常类有哪些?

NullPointerException 空指针异常ClassNotFoundException 指定类不存在NumberFormatException 字符串转换为数字异常IndexOutOfBoundsException 数组下标越界异常ClassCastException 数据类型转换异常FileNotFoundException 文件未找到异常NoSuchMethodException 方法不存在异常IOException IO 异常SocketException Socket 异常

6、异常处理的方式

在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。 捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。

7、项目中是否运用到全局异常?

Java 把异常当做对象来处理。Throwable 是所有错误或异常的超类。Throwable 类有两个直接子类:Error 类和 Exception 类。一般项目中都会有一些业务相关(非 JVM 抛出)的异常,可以使用自定义异常继承相关的异常来抛出有用的异常信息,根据异常示信息进行程序修改。比如空指针异常 NullPointException,可以抛出 message 为“xxx 为空”,例如在进行相关的业务处理时是会进行自定义异常的处理告诉用户相关的异常信息定位异常位置,而不用输出堆栈信息。自定义异常通常是定义一个继承自 Exception 类的子类,一般会直接继承自 Exception 类,而不会继承某个运行时的异常类。对于全局异常,我们项目中使用@ControllerAdvice+@ExceptionHandler来捕获全局的异常,我们根据抛出来的不同的自定义异常做不同的处理.有些异常为了方便查询检索,存储到数据库中,有些异常会通过日志文件的方式存储。(如果这么回答的话,就要考虑你们的日志是按什么方式存储,怎么切分的。比如使用logback按天来进行切割)自己准备好说的内容里面涉及到其他的技术点,要了解一下,防止别人发散发问.

二、Web阶段

1.preparedStatement和Statement的区别

首先二者都是接口,PreparedStatement继承自Statement,PreparedStatement功能更加强大。它们都是调用方法executeQuery执行sql语句的.

在创建的时候不一致,preparedStatement会绑定sql语句因此会有很大使用不同 Statement:( 异构:语句的格式是不同的)a. 只执行单条的sql语句;

b. 只能执行不带参数的sql语句;与PreparedStatement接口对比,适合执行单条且不带参数的sql语句,这种情况执行效率相对较高。

c.运行原理的角度,数据库接收到sql语句后需要对该条sql语句进行编译后才执行;

PreparedStatement:(同构:两个Sql语句可编译部分是相同的,只有参数值不同。)

a、继承自Statement接口(意味着功能相对更加全面),具有预编译的特性,使用PreparedStatement执行SQL命令时,命令会被数据库编译和解析,并放到命令缓冲区.以后每当执行同一个PreparedStatement对象时,预编译的命令就可以重复使用。

b、使用PreparedStatement可以防止SQL注入.安全性好,允许咱们写SQL模板可以避免字符串拼接的麻烦,使用正则表达式过滤掉字符中的特殊字符。在批量处理同构的sql语句时效率高,提高程序的可读性和可维护性。

2、#与$的区别?

相同点;OGNL表达式;都可以用来取值不同点;#可以避免方式sql的注入问题类似于jdbc里面的preparedstatement#;一般使用于动态的传参

$只是简单的字符串拼接类似于里面的statement 设置值时是string类型的时候必须用拼接$;一般用于结构性的sql语句的拼接(结构性的语句:order by + limit)

4、session 和 cookie 是什么?有什么区别?Session与cookie的执行原理?

概念:都是一种会话与跟踪技术,在一次会话中的不同请求之间共享数据的技术。

cookie:(1)、是将数据保存在客户端(浏览器中),(2)、在服务端创建cookie,(3)、然后将数据发送保存到客户端浏览器中

session:(1)、将数据保存在服务器端的会话跟踪技术(2)、sessoinid就是每一个session对象的id值,它是依赖Cookie进行传递的

cookie与session的优点与缺点?(1)、cookie优点; 给服务器减轻压力,提升服务器性能缺点;1、数据信息不安全 2、中文乱码 3、只能保存字符串 4、传输数据量小

(2)、session优点; 1、保存数据在服务端,因此安全性高 2、可以携带任意类型的数据 3、传输数据量大缺点:给服务器造成一定的压力cookie与session的生命周期?

(1)、cookie生命周期; 1、服务器端创建时诞生 2、setMaxAge(int n)方法设置 0设置的时间结束关闭(2)、session的生命周期:1、在服务器端创建的时候诞生 2、可以用方法手动销毁(invalidate():销毁session对象) 2、默认的过期时间是30分钟手动设置【代码方式:session.setMaxInactiveInterval(int s) 、web.xml方式:,单位是分钟】

Cookie:执行原理:

浏览器向服务器发送请求,服务器需要创建cookie,服务器会通过响应携带cookie,在产生响应时会产生Set-Cookie响应头,从而将cookie信息传递给了浏览器;当浏览器再次向服务器发送请求时,会产生cookie请求头,将之前服务器的cookie信息再次发送给了服务器,然后服务器根据cookie信息跟踪客户端状态。

session:执行原理:A、当浏览器第一次发送请求服务器B、遇到服务器端创建Session的代码,就会创建一个Session对象,然后为该Session对象分配一个id即为jsessionId,并以set-Cookie的方式将该id传回给浏览器,浏览器保存起来。C、只要浏览器没有关闭过,当第二次请求时,会自动将jsessionId以Cookie的方式传回给服务器,服务器根据该jsessionId去服务器查询,查到了使用D、至于服务器是否获取和获取出来做什么,跟后期业务有关

5、 如果客户端禁止 cookie 能实现 session 还能用吗?

可以用,session 只是依赖 cookie 存储 sessionid,如果 cookie 被禁用了,可以使用 url 中添加 sessionid 的方式保证 session 能正常使用。

6.请求转发和重定向的区别?

①、请求转发只有一次请求一次响应,重定向有两次请求两次响应.②、请求转发浏览器的地址栏不会发生变化,重定向浏览器地址栏会发送变化,因为重新发送了一次请求.③、请求转发路径不需要带工程名,重定向的路径带工程名.④、请求转发只能在工程内部转发,重定向可以跳转到任意网页,比如百度.

forward:转发:浏览器不感知,url地址栏不变,request中属性可用。redirect: 重定向:浏览器感知-重新发起请求,url地址栏改变,request中属性不可用。

注意:因为请求转发是在一次请求范围内,所以请求转发是能够将Request域中存的值携带过去的.重定向有两次不一样的请求 , 所以存在Request域中的数据会消失. 也就是说要通过Request域传值只能通过请求转发.

7、get和post请求的区别

a) 参数:GET传递的参数只能带URL后面,文本格式QueryString,各浏览器一般有长度限制,一般认为是2083,如果有中文字符更短。提交到服务器端的数据量小。

POST可以传递application/x-www-form-urlencoded的类似QueryString、multipart/form-data的二进制报文格式(支持文件信息嵌入报文传输)、纯文本或二进制的body参数。提交到服务器端的数据量大。参考:http://blog.csdn.net/kimmking/article/details/2051169

b) 用途:GET用于从服务器端获取数据,包括静态资源(HTML|JS|CSS|Image等等)、动态数据展示(列表数据、详情数据等等)。

POST用于向服务器提交数据,比如增删改数据,提交一个表单新建一个用户、或修改一个用户等。

c) 缓存:GET时默认可以复用前面的请求数据作为缓存结果返回,此时以完整的URL作为缓存数据的KEY。所以有时候为了强制每次请求都是新数据,我们可以在URL后面加上一个随机参数Math.random或时间戳new Date().getTime()、或版本号,比如abc.com?a=1&rnd=0.123987之类的。这也是目前一些静态资源后面加一个很长的版本号的原因,jquery-min.js?v=13877770表示一个版本,当页面引用jquery-min.js?v=13877771时浏览器必然会重新去服务器请求这个资源。jQuery.ajax方法,如果cache=false,则会在GET请求参数中附加”_={timestamp}”来禁用缓存。

POST一般则不会被这些缓存因素影响。

d) 安全性:默认对于nginx的access log,会自动记录get或post的完整URL,包括其中带的参数。

对于POST来说,请求的报文却不会被记录,这些对于敏感数据来说,POST更安全一些。

8、servlet 和js、 JSP是什么?有什么区别?

①Servlet:

广义上讲是一个规范,狭义上讲是一个小程序:Servlet 是由 Java 提供用于开发 web 服务器应用程序的一个组件,运行在服务端,由 servlet 容器管理,用来生成动态内容。一个 servlet 实例是实现了特殊接口 Servlet 的 Java 类,所有自定义的 servlet 均必须实现 Servlet 接口

servlet的生命周期: ①、实例化(为对象分配空间) ②、初始化(为对象的属性赋值) ③、请求处理(服务阶段) ④、销毁(服务结束/容器关闭)

servlet的三大职责:

1、接受用户传过来的请求参数2、处理业务 3、页面跳转

servlet与filter过滤器的区别

a、servlet1、第一次访问的时候初始化(可以通过配置提前初始化)2、以后的每一次初始化请求都执行service方法3、初始化以后正常关闭tomcat的时候销毁对象关闭

b、Filter;过滤器1、在tomcat启动的时候初始化2、以后每一次请求都执行doFilter3、正常关闭的时候销毁对象

②、JS (JavaScript);

是一种基于对象的客户端脚本语言。目的是解决服务器端语言。三大核心:ECMAScript(核心);BOM(浏览器对象模型);DOM(文档对象模型);

③、jsp (Java Server Pages):

本质上就是一个 Servlet,它是 Servlet 的一种特殊形式(由 SUN 公司推出),每个 jsp 页面都是一个 servlet实例。运行在后台服务器上,混合在HTML中的java程序段用于控制HTML的动态生成,并且通常负责调用后台,数据库中的数据,形成能够根据使用情况的变化的,具有丰富数据交互效果的页面。

三者区别:Servlet 是 html 代码和 Java 代码分离,侧重逻辑控制,mvc 设计思想中 jsp 位于视图层,servlet 位于控制层。

Js :JavaScript 通常是运行在前台,即运行于用户浏览器的,通常不需要服务器的后台支持(AJAX交互例外);

jsp 是 html 页面中内嵌的 Java 代码,侧重页面显示;

9、JSP的原理

①、客户端通过浏览器向服务器发出请求,在该请求中包含了请求的资源的路径,这样当服务器接收到该请求后就可以知道被请求的内容。

②、服务器根据接收到的客户端的请求来加载相应的JSP文件。

③、Web服务器中的JSP引擎会将被加载的JSP文件转化为Servlet文件(.java)。

④、JSP引擎将生成的Servlet代码编译成Class文件。

⑤、服务器执行这个Class文件。

⑥、最后服务器将执行结果发送给浏览器进行显示。

10、JSP 有哪些内置对象?作用分别是什么?

JSP 有 9 大内置对象:request:封装客户端的请求,其中包含来自 get 或 post 请求的参数;response:封装服务器对客户端的响应;pageContext:通过该对象可以获取其他对象;session:封装用户会话的对象;application:封装服务器运行环境的对象;out:输出服务器响应的输出流对象;config:Web 应用的配置对象;page:JSP 页面本身(相当于 Java 程序中的 this);exception:封装页面抛出异常的对象。

11、jsp四大作用域的层级关系?四大作用域的生命周期?

application>session>request>pageContext :这个大小指的是作用域中对象存活的时间

application:代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域。session:代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。request:代表与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。page:代表与一个页面相关的对象和属性。

JSP四大作用域的生命周期:application` : (一般是当服务器启动的时候到服务器关闭的时候)活到项目死亡,一般可以用于计算当前多少人在访问我们的网站注意: appcation就是ServletContext在JAVA代码中获取上下文路径 getContextPath()获取当前的真实路径 getRealPath(“/“)

session :(浏览器开启的时候开启关闭的时候结束)一次会话, 活到浏览器关闭,一般用于保存登录用户,默认只活半小时,你的浏览器有半个小时没有碰

request : 一次请求 (用得最多)

pageContext: 当前页面 (不用)

12、jQuery与script原生态区别;

jQuery加载事件;可以写多个,依此执行,jQuery加载事件优先于script原生态页面加载事件。script原生态;只能执行一个页面加载事件

13、 spring mvc 和 struts 的区别是什么?

拦截级别:struts2 是类级别的拦截;spring mvc 是方法级别的拦截。数据独立性:spring mvc 的方法之间基本上独立的,独享 request 和 response 数据,请求数据通过参数获取,处理结果通过 ModelMap 交回给框架,方法之间不共享变量;而 struts2 虽然方法之间也是独立的,但其所有 action 变量是共享的,这不会影响程序运行,却给我们编码和读程序时带来了一定的麻烦。拦截机制:struts2 有以自己的 interceptor 机制,spring mvc 用的是独立的 aop 方式,这样导致struts2 的配置文件量比 spring mvc 大。对 ajax 的支持:spring mvc 集成了ajax,所有 ajax 使用很方便,只需要一个注解 @ResponseBody 就可以实现了;而 struts2 一般需要安装插件或者自己写代码才行。

14. 什么是 XSS 攻击,如何避免?

XSS 攻击:即跨站脚本攻击,它是 Web 程序中常见的漏洞。原理是攻击者往 Web 页面里插入恶意的脚本代码(css 代码、Javascript 代码等),当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的,如盗取用户 cookie、破坏页面结构、重定向到其他网站等。预防 XSS 的核心是必须对输入的数据做过滤处理。

15. 什么是 CSRF 攻击,如何避免?

CSRF:Cross-Site Request Forgery(中文:跨站请求伪造),可以理解为攻击者盗用了你的身份,以你的名义发送恶意请求,比如:以你名义发送邮件、发消息、购买商品,虚拟货币转账等。防御手段:验证请求来源地址;关键操作添加验证码;在请求地址添加 token 并验证。

16、简单介绍数据三范式

第一范式:是指数据库表的每一列都是不可分割的基本数据项第二范式:第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一的区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。要求实体的属性完全依赖于主关键字。第三范式:在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。

17、事务四个基本特性或ACID特性、及事务的传播机制、Mysql事务的隔离机制以及解决的问题、分布式事务解决方案?

①、事务四个基本特性

原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状.一致性的定义和完整性约束有关系。这些月数可能包括主键约束、外键约束以及用户自定义的约束。事务执行的前后都是合法的数据状态,不能违背任何的数据完整性。这种完整性体现在业务上就是业务规则的约束,比如业务上要求银行转账前后必须总额一致,从业务的角度来看更容易理解,这也是我们最关心的。隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该造成其丢失。

②、事务传播机制(行为)Propagation

常用的是前4个, REQUIRED 是默认的也是用得最多的REQUIRED :支持当前事务,如果当前没有事务,则新建一个事务SUPPORTS :支持当前事务,当前当前没有事务,就不加事务REQUIRES_NEW :新建事务,如果当前有事务,则把事务挂起NEVER : 不支持事务,如果当前有事务,则抛出异常MANDATORY : 支持当前事务,如果当前没有事务,则抛出异常NOT_SUPPORTED :不运势当前事务,如果当前存在事务,则把事务挂起NESTED :支持当前事务,如果事务存在,则执行一个嵌套事务,如果事务不存在,就新建一个事务。

③、事务隔离机制以及解决的问题

事务并发造成的问题

脏读:读到了其他事务还没有提交的数据。

不可重复读:对某数据进行读取,发现两次读取的结果不同,也就是说没有读到相同的内容。这是因为有其他事务对这个数据同时进行了修改或删除。

幻读:事务 A 根据条件查询得到了 N 条数据,但此时事务 B 更改或者增加了 M 条符合事务 A 查询条件的数据,这样当事务 A 再次进行查询的时候发现会有 N+M 条数据,产生了幻读

不可重复读和幻读的区别:相同点:不可重复读和幻读都是在先后两次读取的时候发现不一致的情况不同点:不可重复读是同一条记录的内容被修改了,重点在于UPDATE或DELETE幻读是查询某一个范围的数据行变多了或者少了,重点在于INSERT

MySQL的事务隔离级别以及机制:

(1)、标准SQL隔离级别MySQL的事务隔离级别有四种:

1.读未提交(read-uncommitted):能读到未提交的数据。会出现脏读、不可重复读、幻读。

2.读已提交(read-committed):读已提交的数据。解决脏读

3.可重复读(repeatable-read):mysql默认的事务隔离级别,查询的都是事务开始时的数据。只会出现幻读。(脏读、不可重复读、幻读)

4.串行读(serializable):完全串行化读,每次都会锁表,读写互相阻塞。最高隔离级别,不会出现脏读,不可重复读,幻读。但会大大影响系统的性能,一般不用。

(2)、InnoDB事务隔离级别机制:

1、锁定读和一致性非锁定读2、当前读和快照读3、隐式锁定和显式锁定

③、事务的隔离级别实现的原理?

标准的sql语句级别:(1)、主要是通过视图的方式来实现的:数据库里面会创建一个视图,访问的时候以视图的逻辑为准.读未提交: 直接返回记录上的最新值,没有视图概念.读已提交: 在每个SQL语句开始执行的时候创建视图,所以在查询SQL执行前如果数据发生修改,也可以读到.可重复读: 在事务启动时创建的视图,整个事务存在期间都用这个视图,所以读到的数据不会发生变化.串行化: 是直接使用加锁的方式来避免并行访问.

InnoDB事务隔离级别:方式一、加锁:在读取数据前,对其加锁,防止其他事务对数据进行修改。方式二、MVCC:多版本并发控制,指的是一种提高并发的技术,生成一个数据请求时间点的一致性数据快照,并用这个快照来提供一定级别的一致性读取.

(3)、InnoDB事务隔离级别保证事务四大特性的实现原理:a、重做日志redo log)保证一致性与持久性,b、回滚日志(undo log)保证原子性,c、使用各种锁来保证隔离性(行锁、表锁)。

④、什么是分布式事务以及解决方案?

(1)、什么是本地事务:

本地事务就是用关系数据库来控制事务,关系数据库通常都具有ACID特性,传统的单体应用通常会将数据全部存储在一个数据库中,会借助关系数据库来完成事务控制。

(2)、什么是分布式事务:

在分布式系统中一次操作由多个系统协同完成,这种一次事务操作涉及多个系统通过网络协同完成的过程称为分布式事务。这里强调的是多个系统通过网络协同完成一个事务的过程,并不强调多个系统访问了不同的数据库,即使多个系统访问的是同一个数据库也是分布式事务,从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

(3)、分布式事务运用场景:

(4)、分布式事务产生的原因:

2.1 数据库分库分表

当数据库单表数据达到千万级别,就要考虑分库分表,那么就会从原来的一个数据库变成多个数据库。例如如果一个操作即操作了01库,又操作了02库,而且又要保证数据的一致性,那么就要用到分布式事务。

2.2 应用SOA化

所谓的SOA化,就是业务的服务化。例如电商平台下单操作就会产生调用库存服务扣减库存和订单服务更新订单数据,那么就会设计到订单数据库和库存数据库,为了保证数据的一致性,就需要用到分布式事务。总结:其实上面两种场景,归根到底是要操作多数据库,并且要保证数据的一致性,而产生的分布式事务的。

(5)、分布式事务的理论:

CAP理论:

CAP理论说的是:在一个分布式系统中,最多只能满足C、A、P中的两个需求。

CAP的含义:

C:Consistency 一致性: 同一数据的多个副本是否实时相同。A:Availability 可用性: 可用性:一定时间内系统返回一个明确的结果则称为该系统可用。P:Partition tolerance 分区容错性(分布式系统的根本): 将同一服务分布在多个系统中,从而保证某一个系统宕机,仍然有其他系统提供相同的服务。

对于一个业务系统来说,可用性和分区容错性是必须要满足的两个条件,并且这两者是相辅相成的。业务系统之所以使用分布式系统,主要原因有两个:

使用AP原因:①、提升整体性能当业务量猛增,单个服务器已经无法满足我们的业务需求的时候,就需要使用分布式系统,使用多个节点提供相同的功能,从而整体上提升系统的性能,这就是使用分布式系统的第一个原因。

②、实现分区容错性单一节点或多个节点处于相同的网络环境下,那么会存在一定的风险,万一该机房断电、该地区发生自然灾害,那么业务系统就全面瘫痪了。为了防止这一问题,采用分布式系统,将多个子系统分布在不同的地域、不同的机房中,从而保证系统高可用性。

这说明分区容错性是分布式系统的根本,如果分区容错性不能满足,那使用分布式系统将失去意义。

如果业务系统时常出现“系统异常”、响应时间过长等情况,这使得用户对系统的好感度大打折扣,因此,我们只能通过牺牲一致性来换取系统的可用性和分区容错性。这也就是下面要介绍的BASE理论。

BASE理论:

CAP理论告诉我们一个悲惨但不得不接受的事实——我们只能在C、A、P中选择两个条件。而对于业务系统而言,我们往往选择牺牲一致性来换取系统的可用性和分区容错性。不过这里要指出的是,所谓的“牺牲一致性”并不是完全放弃数据一致性,而是牺牲强一致性换取弱一致性。下面来介绍下BASE理论。

BA:Basic Available 基本可用整个系统在某些不可抗力的情况下,仍然能够保证“可用性”,即一定时间内仍然能够返回一个明确的结果。只不过“基本可用”和“高可用”的区别是:“一定时间”可以适当延长当举行大促时,响应时间可以适当延长给部分用户返回一个降级页面给部分用户直接返回一个降级页面,从而缓解服务器压力。但要注意,返回降级页面仍然是返回明确结果。S:Soft State:柔性状态同一数据的不同副本的状态,可以不需要实时一致。E:Eventual Consisstency:最终一致性同一数据的不同副本的状态,可以不需要实时一致,但一定要保证经过一定时间后仍然是一致的。

(6)、如何选择CAP还是BASE:

ACID能够保证事务的强一致性,即数据是实时一致的。这在本地事务中是没有问题的,在分布式事务中,强一致性会极大影响分布式系统的性能,因此分布式系统中遵循BASE理论即可。但分布式系统的不同业务场景对一致性的要求也不同。如交易场景下,就要求强一致性,此时就需要遵循ACID理论,而在注册成功后发送短信验证码等场景下,并不需要实时一致,因此遵循BASE理论即可。因此要根据具体业务场景,在ACID和BASE之间寻求平衡。

(7)、分布式事务解决的方案:

常见方案:

XA方案/两阶段提交TCC方案/三阶段提交本地消息表可靠消息最终一致性方案最大努力通知方案

①、XA方案/两阶段提交

XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、Mysql等数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交回滚。

在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等)。因此,二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

第一阶段(提交请求阶段)

协调者节点向所有参与者节点询问是否可以执行提交操作,并开始等待各参与者节点的响应。参与者节点执行询问发起为止的所有事务操作,并将Undo信息和Redo信息写入日志。各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返回一个”同意”消息;如果参与者节点的事务操作实际执行失败,则它返回一个”中止”消息。

有时候,第一阶段也被称作投票阶段,即各参与者投票是否要继续接下来的提交操作。

第二阶段(提交执行阶段)

成功

当协调者节点从所有参与者节点获得的响应消息都为”同意”时:

协调者节点向所有参与者节点发出”正式提交”的请求。参与者节点正式完成操作,并释放在整个事务期间内占用的资源。参与者节点向协调者节点发送”完成”消息。协调者节点收到所有参与者节点反馈的”完成”消息后,完成事务。

失败

如果任一参与者节点在第一阶段返回的响应消息为”终止”,或者协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:

协调者节点向所有参与者节点发出”回滚操作”的请求。参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。参与者节点向协调者节点发送”回滚完成”消息。协调者节点收到所有参与者节点反馈的”回滚完成”消息后,取消事务。

有时候,第二阶段也被称作完成阶段,因为无论结果怎样,协调者都必须在此阶段结束当前事务。

总结:

二阶段提交看起来确实能够提供原子性的操作,但是它存在几个缺点:

1、同步阻塞问题:执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。

2、单点故障:由于(事务管理器)协调者的重要性,一旦协调者发生故障。(本地资源管理器)参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)

3、数据不一致:在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接收到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器无法执行事务提交。于是整个分布式系统便出现了数据不一致的现象。

4、二阶段无法解决的问题:参与者在发出commit消息之后宕机,而唯一接收到这条消息的协调者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交了。太过保守任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

②、三阶段提交(3PC)

3PC其实在2PC的基础上增加了CanCommit阶段,是2PC的变种,并引入了超时机制。一旦事务参与者迟迟没有收到协调者的Commit请求,就会自动进行本地commit,这样相对有效的解决了协调者单点故障的问题。但是,性能和数据一致性问题没有根本解决。

3PC分为三个阶段:CanCommit、PreCommit、DoCommit3.2.1 CanCommit阶段

它跟2PC的准备阶段很像,协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。事务询问:协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应 响应反馈:参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则返回No

3.2.2 PreCommit阶段

协调者根据参与者的响应情况来决定是否可以进行事务的PreCommit操作。根据响应情况,有以下两种可能:假如协调者从所有的参与者获得的反馈都是Yes,那么就会执行事务的与执行。 发送预提交请求:协调者向参与者发送PreCommit请求,并进入Prepared阶段。事务预提交:参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。 响应反馈:如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。假如有任何一个参与者向协调者发送了No响应,或者等待超时,或者协调者都没有接到参与者的响应,那么就执行事务的中断。发送中断请求:协调者向所有参与者发送abort请求。中断事务:参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。

3.2.3 doCommit阶段

该阶段进行真正的事务提交,也可以分为以下两种情况:

执行提交:发送提交请求:协调接收到参与者发送的ACK响应,那么将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。事务提交:参与者接收到doCommit请求之后,执行正式的事务提交,并在完成事务提交之后释放所有事务资源。 响应反馈:事务提交完之后,向协调者发送ACK响应。 完成事务:协调者接收到所有参与者的ACK响应之后,完成事务。中断事务协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。 发送中断请求:协调者向所有参与者发送abort请求 事务回滚:参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。 反馈结果:参与者完成事务回滚之后,像协调者发送ACK消息。中断事务:协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

总结:

相对于2PC而言,3PC对于协调者和参与者都设置了超时时间,而2PC只有协调者才拥有超时时间机制。这个优化解决了,参与者在长时间无法与协调者节点通讯的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。但是仍然没有解决数据一致性问题,即在参与者收到PreCommit请求后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。

优点:跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些

缺点: TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。

③、TCC方案补偿事务

TCC(Try-Confirm-Cancel)又称补偿事务。它实际上与2PC、3PC一样,都是分布式事务的一种实现方案而已。它分为三个操作:

Try阶段:主要是对业务系统做检测及资源预留。Confirm阶段:确认执行业务操作。Cancel阶段:取消执行业务操作。

TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在DB层面,而TCC本质上就是应用层面的2PC,需要通过业务逻辑来实现。它的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提交吞吐量。

不过对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。

④、本地消费表

大概流程:

A系统在自己本地一个事务里操作同时,插入一条数据到消息表接着A系统将这个消息发送到MQ中去B系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息B系统执行成功之后,就会更新自己本地消息表的状态以及A系统消息表的状态如果B系统处理失败了,那么就不会更新消息表状态,那么此时A系统会定时扫描自己的消息表,如果有没处理的消息,会再次发送到MQ中去,让B再次处理这个方案保证了最终一致性,哪怕B事务失败了,但是A会不断重发消息,直到B那边成功为止

原理:优点:一种非常经典的实现,避免了分布式事务,实现了最终一致性。

缺点:消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

⑤、消息事务最终一致性方案

所谓的消息事务就是基于消息中间件的两阶段提交,本质上是中间件的一种特殊利用,他是将本地事务和发消息放在一个分布式事务里,保证要么本地操作成功并且对外发消息成功,要么两者都失败,开源的RocketMQ就支持这一特性,

大概流程:

A系统先发送一个prepared消息到mq,如果这个prepared消息发送失败那么就直接取消操作别执行了如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚消息如果发送了确认消息,那么此时B系统会接收到确认消息,然后执行本地的事务mq会自动定时轮询所有prepared消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认消息?那是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,别确认消息发送失败了。 这个方案里,要是系统B的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如B系统本地回滚后,想办法通知系统A也回滚;或者是发送报警由人工来手工回滚和补偿

优点:实现了最终一致性,不需要依赖本地数据库事务。

缺点:实现难度大,主流MQ不支持,RocketMQ事务消息部分代码也未开源。

⑥、最大努力通知方案

大概流程:系统A本地事务执行完之后,发送个消息到MQ这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统B的接口

要是系统B执行成功就ok了;要是系统B执行失败了,那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃优点:可以在一定程度上允许是少数的分布式事务失败,一般用在对分布式要求不严格的情况下,比如说记录日志或状态

总结:

以上五种方案都是可以解决分布式事务的问题,其中可靠消息最终一致性方案是我们平常用的最多的一种方案。

(8) 、什么是分布式锁?

1、为什么需要:多个线程访问数据的时候,保证数据的原子性,需要锁2、什么是分布式锁:就是在在分布式/集群环境下,保证某个公共资源只能在同一时间被多进程应用的某个进程的某一个线程访问时使用锁。(锁住的是进程)3、分布式锁的特点:互斥性:同一时间只能一个节点获取到锁,其他节点需要等待获取到锁的节点释放了锁才可以获取到锁,而这里的等待一般是通过阻塞,和自旋两种方式安全性:解铃还须系铃人,只能释放自己的锁不能误删别人的锁 死锁:比如在节点宕机时最容易出现锁没被释放的问题,然后出现死锁,所以做锁的过期 容错:当Redis宕机,客户端仍然可以释放锁

可重入:获取锁失败可以重新尝试获取锁

使用场景:(库存超卖)

1:常规的我们多线程访问同一代码块的时候,为了保证同一时间只能由一个线程访问,保证数据安全一致性,通常我们使用synchronized关键字来对方法加锁,以达到保证数据安全性。

2:现在越来越多的项目,为了追求性能与高并发,采用了soa架构,微服务架构,于是就会出现多个模块单独的服务。这个时候呢就会有一个问题,如何保证多个节点的现场同步执行呢?这种情况呢,就会用到了分布式锁。

(9)、分布式锁的解决方案与实现有哪些呢?

1)、数据库解决方案思路:

①、使用数据库的唯一主键来实现锁!②、使用数据库的索引UNIQUE ③、悲观锁(排他锁)- For Update④、乐观锁-不上锁—-加版本号⑤、mysql innodb行锁

a.数据库建一张表,字段方法名并且作为唯一性,当一个方法执行时插入,则相当于获得锁,其他线程将无法访问,方法执行完则释放锁。

但是上面这种存在问题:(1)、数据库单点,出现故障则将导致系统不可用。(2)、没有失效时间,一旦操作方法异常,导致一直没有解锁,也将导致其他不可用用。

b.使用select from user u where username = ‘’ for update 来对记录加上排他锁。操作完成后使用commit命令释放锁。

2)、基于redis缓存实现(放入redis共享锁): 使用redis的指令:通常使用setnx方法,incr方法等进行实现

通常有Memcached、Redis实现等,以下以Redis实现分布式锁为例

思路:主要用到的redis函数是setnx(),这个应该是实现分布式锁最主要的函数。首先是将某一任务标识名(这里用Lock:order作为标识名的例子)作为键存到redis里,并为其设个过期时间,如果是还有Lock:order请求过来,先是通过setnx()看看是否能将Lock:order插入到redis里,可以的话就返回true,不可以就返回false

3).Zookeeper分布式锁:使用api生成临时节点实现锁!

大致思路:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。

ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上,所以性能上不如基于缓存实现。————————————————

18、mysql数据库的最大连接数?

1、查看最大连接数show variables like ‘%max_connections%’;

2、修改最大连接数set GLOBAL max_connections = 200;

大家都知道MySQL最大连接数的默认值是100, 这个数值对于并发连接很多的数据库的应用是远不够用的,当连接请求大于默认连接数后,就会出现无法连接数据库的错误,因此我们需要把它适当调大一些。在使用MySQL数据库的时候,经常会遇到这么一个问题,就是“Can not connect to MySQL server.oo many connections”-mysql 1040错误,这是因为访问MySQL且还未释放的连接数目已经达到MySQL的上限。通常,mysql的最大连接数默认是100, 最大可以达到16384。(16384=2的14次方)

19、说一下mysql分页?Oracle的分页

mysql:sql语句是使用limit关键字进行分页

/MySQL分页,因为MySQL没有rownum/select from (select rownum r2 ,a. from (SELECT @rownum:=@rownum+1 as rownum, user.id,user.username,user.password FROM (SELECT @rownum:=0) r,user) awhere rownum3;

Oracle:通过嵌套查询进行分页select from( select rownum r,a from tabName where rownum 10

20、简单说下你对jdbc的理解

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API(Application Programming Interface),可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。它就是Java与数据库的连接的桥梁或者插件,用Java代码就能操作数据库的增删改查、存储过程、事务等。我们用JAVA就能连接到数据库;创建SQL或者MYSQL语句;执行SQL或MYSQL的查询数据库;查看和修改结果记录。4.采用JDBC访问数据库的基本步骤:a) 注册驱动b) 建立数据库连接(Connection)c) 准备 SQL 语句d) 获取 SQL 语句发送器(Statement)e) 发送并执行 SQL 语句, 得到结果集(ResultSet)f) 处理结果集g) 关闭资源(ResultSet, Statement, Connection)

21、写一个简单的jdbc程序

//加载驱动Class.forName(“com.mysql.jdbc.Driver”);//创建连接Connection connection=DriverManager.getConnection(“jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8”,”root”, “123456”);//创建执行对象Statement createStatement = connection.createStatement();//创建sql语句String sql = “CREATE TABLE emp1 (“ + “ id bigint(20) NOT NULL AUTO_INCREMENT,” + “ age int(11) DEFAULT NULL,” + “ name varchar(255) DEFAULT NULL,” + “ PRIMARY KEY (id)” + “) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;” ;//执行事务createStatement.execute(sql);//事务关闭createStatement.close();connection.close();

22、数据库连接池作用

1.资源重用,避免了数据库连接频繁建立、关闭的开销2.更快的系统响应速度,直接从连接池中获取连接,响应速度加快控制资源的使用。如 果不使用连接池,每次访问数据库都需要创建一个连接,这样系统的稳定性受系统连接 需求影响很大,很容易产生资源浪费和高负载异常。连接池能够使性能最大化,将资源 利用控制在一定的水平之下。连接池能控制池中的连接数量,增强了系统在大量用户应 用时的稳定性。常用的数据库连接池:DBCP、C3P0、Druidps:池化技术(扩展):简单点来说,就是提前保存大量的资源,以备不时之需。对于线程,内存,数据库的连接对象等等,这些都是资源,程序中当创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响整个程序性能的瓶颈。池化技术主要有线程池,内存池,数据库连接池,对象池等等,对象池就是提前创建很多对象,将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来使用,使用完成之后再交还保存,使得可以被重复使用

23、文件上传三要素:

(1) 表单的提交的方式必须是POST请求(get请求对提交的数据)(2) 表单中必须有一个文件上传项:,文件上传项必须有name属性和值;(3) 表单的enctype属性的值必须是multipart / form-data

24、一个select语句的关键字的定义顺序是怎么样的?

定义顺序:SELECT DISTINCT FROM JOIN ON WHERE GROUP BY HAVING ORDER BY LIMIT

执行顺序:(7) SELECT (8) DISTINCT (1) FROM (3) JOIN (2) ON (4) WHERE (5) GROUP BY (6) HAVING (9) ORDER BY (10) LIMIT 顺序: from ,on ,join ,where,group by , having ,select,order by ,limit

25.一个select语句中关键字是按照什么顺序执行的?

from ,on ,join ,where,group by , having ,select,order by ,limit

26.Mybatis的Mapper接口为什么可以@Autowire直接注入

Mybatis 通过注解@MapperScan 下的@Import注解加载,MapperScannerRegistrar类,此类继承了ImportBeanDefinitionRegistrar类,对bean的注册处理,在注册之前会拿到 @MapperScan 的参数值,mapper 包路径,然后调用new ClassPathMapperScanner(registry) 类去扫描,ClassPathMapperScanner extends ClassPathBeanDefinitionScanner,重写doScan方法,定义扫描规则,对扫描结果进行更改 BeanDefinition 的beanClass 进行替换成 MapperFactoryBeanClass;

mapper接口是如何被实例化,然后可以使用@Autowired注入?

mapper接口没有被实例化,是通过 FactoryBean 的方式注入到 IOC 中,通过调用getObject方法生成代理对像 @Autowired的;

27.在Mybatis中,mapper.xml有一个sql为: select from user ,如何在不修改sql的基础上在sql后面加上 where id = 1 ?

运用动态sql语句的标签进行操作

28.MyBatis的动态SQL标签有哪些?

where、if、choos、when、foreach、set

29、Mybatis的mapper如何传递多个参数①、dao按照获取的顺序进行获取、②、打注解@param、③、封装成一个map进行传递

30、嵌套子查询和JOIN有什么区别?

嵌套子查询:sql语句中还有sql语句,子查询先查询、效率低 索引失效Join: join查询关联表效率更高。

31、在ResultMap中多对一关联对象查询用什么?一对多关联查询用什么?

一对一:assaociation用于配置一对一关系property:order里面的user属性JAVAtYPE:user的数据类型,支持别名—>一对多:collection用于对应一对多关联property:user中order的属性oftype:order的数据类型支持别名

多对一:assaociation用于配置一对一关系property:order里面的user属性JAVAtYPE:user的数据类型,支持别名—>封装结果是集合用collection,是对象就用assaociation

数据库:

一、Mysql

1、MySQL的优化 尽量减少不必要的要求 2. 冗余数据的处理; 3. 大表拆小表,有大数据的列单独拆成小表4. 把常用属性分离成小表5. 添加对应的索引

· 为搜索字段创建索引。· 避免使用 select *,列出需要查询的字段。· 垂直分割分表。· 选择正确的存储引擎。

2、MySQL的执行流程 客户端发送一条查询给服务器;2. 服务器通过权限检查之后,先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;3. 服务器端进行SQL解析、预处理,再由优化器根据该SQL所涉及到的数据表的统计信息进行计算,生成对应的执行计划;4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;5. 将结果返回给客户端。SQL执行的最大瓶颈在于磁盘的IO,即数据的读取;不同SQL的写法,会造成不同的执行计划的执行,而不同的执行计划在IO的上面临完全不一样的数量级,从而造成性能的差距;所以,我们说,优化SQL,其实就是让查询优化器根据程序猿的计划选择匹配的执行计划,来减少查询中产生的IO;

3、MySQL数据库的常见的索引有几种实现方式?

1.b-tree使用平衡树实现索引,是MySQL中使用最多的索引类型;在innodb中,存在两种索引类型,第一种是主键索引(primary key),在索引内容中直接保存数据的地址;第二种是其他索引,在索引内容中保存的是指向主键索引的引用;所以在使用innodb的时候,要尽量的使用主键索引,速度非常快;2,hash:把索引的值做hash运算,并存放到hash表中,使用较少,一般是memory引擎使用;优点:因为使用hash表存储,按照常理,hash的性能比B-TREE效率高很多。 1,hash索引只能适用于精确的值比较,=,in,或者;无法使用范围查询;2,无法使用索引排序;3,组合hash索引无法使用部分索引;4,如果大量索引hash值相同,性能较低;具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。

4、MySQL数据库的常见优化

1、索引,建立索引是数据库优化各种方案之中成本最低,见效最快的解决方案.索引一般加在查询条件的关键字上,如果有多个查询条件关键字,还可以添加组合索引,写sql的时候需要注意,索引字段和sql字段需要保持一致,否则索引会无效2. 分库分表分区 分库,可以按照业务分库,分流数据库并发压力,使数据库表更加有条理性,最起码更加好找吧 分表,刚才说了,索引适合应对百万级别的数据量,千万级别数据量使用的好,勉强也能凑合,但如果是上亿级别的数据量3. 数据库引擎 myisam innodb4. 预处理 一般来说,实时数据(当天的数据)还是比较有限的,真正数据量比较大的是历史数据,基于大表历史数据的查询,如果再涉及一些大表关联,这种sql是非常难以优化的5. MySQL like查询6. 读写分离

5、MySQL的行锁和表锁

MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低。表锁则不会出现死锁的情况。行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高。行锁会出现死锁情况。行锁包括:共享锁和排他锁。共享锁(S Lock)又称:读锁、s锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。排它锁(X Lock)又称:写锁、x锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁上共享锁的写法:lock in share mode例如: select math from zje where math>60 lock in share mode;上排它锁的写法:for update例如:select math from zje where math >60 for update;

锁冲突:例如说事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)

死锁:例如说两个事务,事务A锁住了1~5行,同时事务B锁住了6~10行,此时事务A请求锁住6~10行,就会阻塞直到事务B施放6~10行的锁,而随后事务B又请求锁住1~5行,事务B也阻塞直到事务A释放1~5行的锁。死锁发生时,会产生Deadlock错误。

6、MySQL的主从配置

1、添加一个新的MySQL实例(1)复制MySQL安装目录(2)修改新MySQL的相关配置(端口,安装目录,数据目录)(3)为新的MySQL创建数据目录(4)为新的MySQL创建window系统服务(5)检查创建的系统服务,并且启动测试 2、配置主从3、启动主数据库执行 show master status命令4、配置从服务器5、启动从服务器6、恢复主数据库的备份7、让从数据库指定Master库8、启动MySQL

7、MySQL如何实现读写分离

1、一个service方法必须定位到唯一的数据库上2、引入路由DataSource(1)在应用中,需要自己去确定这个要访问的真实目标DataSource(2)让路由DS知道哪些真实DataSource和他门对应的名字(3)让路由DS根据传入的名字去返回真实的DS3、完成读写分离(1) 1,认识Spring中的AbstractRountingDataSource;(2) 在Spring中提供了AbstractRountingDataSource来完成路由DS的功能;(3) 1,targetDataSources:用于配置真实的datasource,这个属性是一个Map,Map的key就是DS的名字,Map的value是真实的DS对象;(4) 2,defaultTargetDataSource:如果路由DS没有找到你当前请求的DS,直接使用默认的DS;(5) 3,abstract Object determineCurrentLookupKey():这个方法是需要我们自己实现的,这个方法需要返回一个值,这个值就是DS的名字;这个方法就是让应用(我们)提供给Spring怎么找DS名字的逻辑;(6) 2,步骤:(7) 1,创建一个继承AbstractRountingDataSource的对象,并在Spring中配置;(8) 2,修改原来的datasource的配置:

8、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?

· 表类型如果是 MyISAM ,那 id 就是 8。· 表类型如果是 InnoDB,那 id 就是 6。InnoDB 表只会把自增主键的最大 id 记录在内存中,所以重启之后会导致最大 id 丢失。

9、如何获取当前数据库版本?

使用 select version() 获取当前 MySQL 数据库版本。

10、char 和 varchar 的区别是什么?

· char(n) :固定长度类型,比如订阅 char(10),当你输入”abc”三个字符的时候,它们占的空间还是 10 个字节,其他 7 个是空字节。chat 优点:效率高;缺点:占用空间;适用场景:存储密码的 md5 值,固定长度的,使用 char 非常合适。· varchar(n) :可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。所以,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,二者使用需要权衡。

11、float 和 double 的区别是什么?

· float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。· double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。

12、MySQL 的内连接、左连接、右连接有什么区别?

内连接关键字:inner join;左连接:left join;右连接:right join。内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示出来,右边的表显示出符合条件的数据;右连接正好相反。

13、怎么验证 MySQL 的索引是否满足需求?

使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。explain 语法:explain select * from table where type=1。

14、说一下 MySQL 常用的引擎?

· InnoDB 引擎:mysql 5.1 后默认的数据库引擎,提供了对数据库 acid 事务的支持,并且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎是不支持全文搜索,同时启动也比较的慢,它是不会保存表的行数的,所以当进行 select count(*) from table 指令的时候,需要进行扫描全表。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。·

MyIASM 引擎:不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率会降低。不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。

15、MySQL 问题排查都有哪些手段?

· 使用 show processlist 命令查看当前所有连接信息。· 使用 explain 命令查询 SQL 语句执行计划。· 开启慢查询日志,查看慢查询的 SQL。

二、Redis

1、Redis 是什么,使用场景、有什摸功能?

Redis 是什么?是一种非关系型数据库,严格说是一个存储数据的中间件,完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。 使用场景:令牌机制登录,热点数据存储,如商品分类,用户的信息,帖子点赞,点赞数,浏览数Redis 最适合的场景?(做缓存数据、计数器的应用 、实时防攻击系统、定时的有效期、自动去重应用)1、会话缓存(Session Cache)最常用的一种使用Redis 的情景是会话缓存(session cache)。用 Redis 缓存会话比其他存储(如Memcached)的优势在于:Redis 提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用 Redis 来缓存会话的文档。甚至广为人知的商业平台Magento 也提供 Redis 的插件。2、全页缓存(FPC)除基本的会话 token 之外,Redis 还提供很简便的 FPC 平台。回到一致性问题,即使重启了 Redis 实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似 PHP 本地 FPC。再次以 Magento 为例,Magento 提供一个插件来使用 Redis 作为全页缓存后端。此外,对 WordPress 的用户来说,Pantheon 有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。3、队列Reids 在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得 Redis 能作为一个很好的消息队列平台来使用。Redis 作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。如果你快速的在 Google 中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用 Redis 创建非常好的后端工具,以满足各种队列需求。例如,Celery 有一个后台就是使用 Redis 作为 broker,你可以从这里去查看。4,排行榜/计数器Redis 在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis 只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的 10 个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行: ZRANGE user_scores 0 10 WITHSCORES Agora Games 就是一个很好的例子,用 Ruby 实现的,它的排行榜就是使用 Redis 来存储数据的,你可以在这里看到。5、发布/订阅最后(但肯定不是最不重要的)是 Redis 的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用 Redis 的发布/订阅功能来建立聊天系统!Redis 有哪些功能?

数据缓存功能分布式锁的功能支持数据持久化支持事务支持消息队列 2、Redis 的支持数据类型?答:Redis 支持五种数据类型:string(字符串,512M 大小),hash(哈希),list(列表), set(集合)及 zsetsorted set:有序集合)。 我们实际项目中比较常用的是 string,hash 如果你是 Redis 中高级用户,还需要 加上下面几种数据结构 HyperLogLog、Geo、Pub/Sub。 如果你说还玩过 Redis Module,像 BloomFilter,RedisSearch,Redis-ML,面 试官得眼睛就开始发亮了。 3、Redis持久化方式:RDB、AOF文件存储的方式;A、方式一:RDB文件存储数据的方式;并发量高的时候。何时把数据存储到磁盘(rdb文件)?RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照,默认开启该模式.——正常关闭redis服务的时候B、方式二:AOF文件存储的方式;手动开启AOF模式(582行、no改为yes)rdb和aof的特点: 4.redis优化-.淘汰策略1、为什莫淘汰数据?选择合适的淘汰策略、进行数据淘汰、淘汰redis无效的数据,达到存储数据都是有效的、节约内存。2、淘汰策略:(config里面设置 526开启上线内存,到549行)volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最 少使用的数据淘汰 volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过 期的数据淘汰 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意 选择数据淘汰 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰 no-enviction(驱逐):禁止驱逐数据 注意这里的 6 种机制,volatile 和 allkeys 规定了是对已设置过期时间的数据集淘 汰数据还是从全部数据集淘汰数据,后面的 lru、ttl 以及 random 是三种不同的 淘汰策略,再加上一种 no-enviction 永不回收的策略。 使用策略规则: 1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率 低,则使用 allkeys-lru 2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random

5、Redis分布式项目中央缓存的问题

(1)、分布式项目缓存的四大问题点a、缓存穿透:查询根本不存在的key 缓存中没有数据,但是数据库中有,此时大量请求过来,直接到达数据库,导致数据库压力过大宕机

解决方案:1. 布隆过滤器 (对key进行过滤如果不存在直接返回)2. 查询出来的不存在的数据null 直接以该key存入redis 后续请求就可以从缓存中获取到该key

b、缓存击穿:缓存中没有数据,但是数据库中有,此时大量请求过来,直接到达数据库,导致数据库压力过大宕机

解决方案: 1.可以让部分请求去数据取数据然后放入缓存其他请求走缓存,去数据库获取数据的操作进行加锁(去数据库取数据存入缓存)(双重校验)2.热点数据永不过期

C、缓存雪崩:缓存中的数据在同一时间节点同时过期,导致请求大量到达数据库,导致数据库压力过大宕机

解决方案:1. 数据的过期时间都是用随机时间2. 热点数据永不过期

d、缓存双写一致性(分布式项目的数据更新与缓存数据的问题)先更新数据库、在更新缓存先删缓存再更新数据库延时双删除 如果遇到删除不成功的放入消息队列重试 重试多次仍不成功 记录日志后台系统手动处理先更数据库,再删除缓存(外面常用)

6、Redis 相比 Memcached 有哪些优势?

相同点:都是key-value Nosql,数据存储在内存中,读写效率高,都支持存储过期.

不同点:1、Memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰 富的数据类 2、Redis 的速度比 Memcached 快很 可以持久化其数据 1)redis支持持久化2)redis支持存储类型更多

7、Memcache 与 Redis 的区别都有哪些?

1、存储方式 Memecache 把数据全部存在内存之中,断电后会挂掉,数据不能 超过内存大小。 Redis 有部份存在硬盘上,这样能保证数据的持久性。 2、数据支持类型 Memcache 对数据类型支持相对简单。 Redis 有复杂的数据类 型。 3、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议 不一样。 Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话, 会浪费一定的时间去移动和请求。

8、Redis 是单进程单线程的?

答:Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消 除了传统数据库串行控制的开销。

9、为什么redis 需要把所有数据放到内存中?

答:Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数 据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中, 磁盘 I/O 速度为严重影响 redis 的性能。在内存越来越便宜的今天,redis 将会越 来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不 能继续插入新值。

10、Redis 的同步机制了解么?

答:Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave, 并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制 节点,复制节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知主节点 将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

11、是否使用过 Redis 集群,集群的原理是什么?

1)、Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为 master,继续提供服务。 2)、Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行 分片存储。

12、Redis 集群方案什么情况下会导致整个集群不可用?

答:有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了, 那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用。

13、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?

答:Redisson(redis集群的分布式锁):先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。这时候对方会告诉你说你回答得不错,然后接着问如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了,那会怎么样?这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得 set 指令有非常复杂的参数,这个应该是可以同时把 setnx 和expire 合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。Jedis、lettuce 等等,官方推荐使用 Redisson。

14、Jedis 与 Redisson 对比有什么优缺点?

答:Jedis 是 Redis 的 Java 实现的客户端,其 API 提供了比较全面的 Redis 命令的支持;Redisson 实现了分布式和可扩展的 Java 数据结构,和 Jedis 相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等 Redis 特性。Redisson 的宗旨是促进使用者对 Redis 的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

15、说说 Redis 哈希槽的概念?

答:Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

16、Redis 集群的主从复制模型是怎样的?

答:为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所 以集群使用了主从复制模型,每个节点都会有 N-1 个复制品.

17、Redis 集群会有写操作丢失吗?为什么?

答:Redis 并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可 能会丢失写操作。

18、Redis 集群之间是如何复制的?

答:异步复制24、Redis 集群最大节点个数是多少? 答:16384 个。

19、Redis 集群如何选择数据库?

答:Redis 集群目前无法做数据库选择,默认在 0 数据库。

20、怎么测试 Redis 的连通性?

答:使用 ping 命令。

21、怎么理解② Redis 事务?

答: 1)事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 2)事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

22、Redis 事务相关的命令有哪几个?

答:MULTI、EXEC、DISCARD、WATCH

23、Redis key 的过期时间和永久有效分别怎么设置?

答:EXPIRE 和 PERSIST 命令。Explpe persist

24、Redis 如何做内存优化?

答:尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用 的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比 如你的 web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码 设置单独的 key,而是应该把这个用户的所有信息存储到一张散列表里面.

25、Redis 回收进程如何工作的?

答:一个客户端运行了新的命令,添加了新的数据。Redi 检查内存使用情况,如 果大于 maxmemory 的限制, 则根据设定好的策略进行回收。一个新的命令被执 行,等等。所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地 回收回到边界以下。如果一个命令的结果导致大量内存被使用(例如很大的集合 的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。

26、都有哪些办法可以降低 Redis 的内存使用情况呢?

答:如果你使用的是 32 位的 Redis 实例,可以好好利用 Hash,list,sorted set,set 等集合类型数据,因为通常情况下很多小的 Key-Value 可以用更紧凑的方式存放 到一起。

27、Redis 的内存用完了会发生什么?

答:如果达到设置的上限,Redis 的写命令会返回错误信息(但是读命令还可以正 常返回。)或者你可以将 Redis 当缓存来使用配置淘汰机制,当 Redis 达到内存 上限时会冲刷掉旧的内容。

28、一个 Redis 实例最多能存放多少的 keys?

List、Set、

Sorted Set 他们最多能存放多少元素? 答:理论上 Redis 可以处理多达 232 的 keys,并且在实际中进行了测试,每个实例至少存放了 2 亿 5 千万的keys。我们正在测试一些较大的值。任何 list、set、和 sorted set 都可以放 232 个元素。换句话说,Redis 的存储极限是系统中的可 用内存值。

29、MySQL 里有 2000w 数据,redis 中只存 20w 的

数据,如 何保证 redis 中的数据都是热点数据?

答:Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。 相关知识:Redis 提供 6 种数据淘汰策略: volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最 少使用的数据淘汰 volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过 期的数据淘汰第 130 页 共 485 页 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意 选择数据淘汰 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰 no-enviction(驱逐):禁止驱逐数据

30、如果有大量的 key 需要设置同一时间过期,一

般需要注意

什么? 答:如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能 会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一 些。

31、使用过 Redis 做异步队列么,你是怎么用的?

答:一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有 消息的时候,要适当 sleep 一会再重试。 如果对方追问可不可以不用 sleep 呢? list 还有个指令叫 blpop,在没有消息的时候,它会阻塞住直到消息到来。如果对 方追问能不能生产一次消费多次呢?使用 pub/sub 主题订阅者模式,可以实现 1:N 的消息队列。 如果对方追问 pub/sub 有什么缺点? 在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 RabbitMQ 等。 如果对方追问 redis 如何实现延时队列? 我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这 么详细。但是你很克制,然后神态自若的回答道:使用 sortedset,拿时间戳作为 score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令 获取 N 秒之前的数据轮询进行处理。到这里,面试官暗地里已经对你竖起了大拇 指。但是他不知道的是此刻你却竖起了中指,在椅子背后。

32、Redis为什么是单线程的而不是多线程的?从cpu的角度来看,单线程和多线程有什么性能的区别?为什么单线程也能实现这么高的性能?

单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。绝大部分请求是纯粹的内存操作(非常快速)

采用单线程,避免了不必要的上下文切换和竞争条件非阻塞IO - IO多路复用

33、有没有做Redis的集群?有哪几种方式,Redis的集群最少要有多少个节点?如果其中一个节点挂掉会怎样?如果只有两个主节点Redis能不能跑起来?

有主从模式,和集群模式.需要6个节点,3主三从.对应的从节点会变成主节点继续工作.答案2:PS: Redis三种集群方案:https://blog.csdn.net/sanpo/article/details/52839044Redis常见的集群方案有三种:1. 主从2. 哨兵机制(sentinel )3. 集群(redis cluster)三种集群方式原理各不相同, 我们使用的是3.x之后官方推荐的redis cluster方式集群,三主三从.其中一个节点挂掉其他节点能不能提供服务是可以通过cluster-require-full-coverage yes 进行配置的, yes 表示有节点挂掉其他可达节点也将停止提供服务, no 则相反更深入一些的话,会涉及到怎么解决节点挂掉后解决可用性的问题,大家可以参考这篇文章: https://yq.aliyun.com/ziliao/411825

34、Redis分布式锁,解决的是分布式的线程问题,Redis分布式锁的实现思路,怎样做到线程安全?

分布式锁无非就是使用指定的标的物作为标识, 以此判断执行某个操作的权限是否已经被占用,如果被占用该线程就继续等待,没有被占用就可以对标的物加锁然后执行操作从原理上来讲实现分布式锁的方式非常多,比如使用指定的文件,使用zookeeper中的指定节点等都可以使用Redis作为分布式锁的原理其实就是: 1. 获取锁的服务在Redis中创建指定的key2. 如果其他服务判断该key存在并且没有过期就认为指定的操作已经被别的服务加锁,继续等待. 3. 如果判断指定的key不存在或者已经过期, 则认为没有人占用锁,或者锁已经超时导致失效. 就可以新建/重置key 标识自己占用了该锁, 之后占用锁的服务就可以指定对应的操作

35、Redis 实现分布式锁原理流程?

Redis提供了一个命令setnx 可以来实现分布式锁,该命令只在键 key 不存在的情况下将键 key 的值设置为 value ,若键 key 已经存在,则 SETNX 命令不做任何动作。根据这一特性我们就可以制定Redis实现分布式锁的方案了。

简单理解就是:如果三个服务同时抢锁,服务A抢先一步执行setnx(lock_stock,1)加上锁,那么当服务B在执行setnx(lock_stock,1)加锁的时候就会失败,服务C也一样,服务A抢到锁执行完业务逻辑后就会释放锁,可以使用del(lock_stock)删除锁,其他服务就可以执行setnx(lock_stock,1)加锁了

36、Redis 分布式锁有什么缺陷?

Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

37、Redisson(redis集群的分布式锁):

先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。这时候对方会告诉你说你回答得不错,然后接着问如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了,那会怎么样?这个锁就永远得不到释放了。紧接着你我记得 set 指令有非常复杂的参数,这个应该是可以同时把 setnx 和 expire 合成一条指令来用的!在Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是默认30秒钟,也可以通过修改Config.lockWatchdogTimeout的枷锁时间来另行指定。另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

以上是Redisson官方文档对分布式锁的解释总结下来有两点

Redisson加锁自动有过期时间30s,监控锁的看门狗发现业务没执行完,会自动进行锁的续期(重回30s),这样做的好处是防止在程序执行期间锁自动过期被删除问题当业务执行完成不再给锁续期,即使没有手动释放锁,锁的过期时间到了也会自动释放锁

三、主流框架阶段

1.Mybatis、Spring、SpringMVC,SpringBoot,SpringCloud的区别?

①、MyBatis

(1)、MyBatis是一个ORM的数据库持久化框架;但是是一个半自动的ORM的框架全自动的ORM的框架;(Hibernate,JPA)(2)、Mybatis底层还是原生的JDBC代码,对JDBC代码的封装;作用;操作数据库关键词概念;ORM; 可以解决第一个问题对象关系映射(Object Relational Mapping,简称ORM):是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术;

Mybatis缓存:

1、缓存定义:缓存是一种典型的“以空间换时间”的策略。2、MyBatis支持缓存:一级缓存:Mybatis的一级缓存是指Session缓存(默认开启的)。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。缓存对象存储周期为第一次获取,到sqlsession被销毁掉,或是sqlSession().clearCache();

也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。

二级缓存:Mybatis的二级缓存是指mapper映射文件或者指的是SqlSessionFactory级别缓存,缓存对象存储周期为第一次获取,到SqlSessionFactory被销毁掉(应用停止了)。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的。

二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。cacheEnabled默认是启用的,只有在该值为true的时候,底层使用的Executor才是支持二级缓存的CachingExecutor。具体可参考Mybatis的核心配置类org.apache.ibatis.session.Configuration的newExecutor方法实现。————————————————3、实现缓存默认情况下,只开启一级缓存,如果需要开启二级缓存我们需要在Mapper.xml添加一个标签和在主配置文件中;

Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

②、spring

是一个轻量级的、开源DI、IOC、AOP的容器框架, Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring的DI、IOC、AOP等. IOC 提供了依赖注入的容器, aop解决了面向横切面编程,然后在此两者的基础上实现了其他延伸产品的高级功能;

AOP(Aspect Oriented Programming): 面向切面编程(抽取代码)作用 : 解耦 , 集成其它框架,让咱们代码更加的优雅,多人开发更加容易

③、SpringMVC:

和servlet一样前段控制器,springMvc是spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染,属于spring框架中WEB层开发的一部分;

springMVC执行流程——面试题

1、客户端将请求统一提交到DispatcherServlet;(前端控制器)2、DispatcherServlet会将请求交给HandlerMapping(处理器映射器)进行请求映射,匹配该请求的Handler;3、DispatcherServlet再请求HandlerAdapter(处理器适配器)调用相应的Handler处理请求,并向前端控制器返回一个ModelAndView对象;4、DispatcherServlet将ModelAndView对象交给ViewResoler视图解析器处理,返回指定的视图View;5、DispatcherServlet 对 View 进行渲染(即将模型数据填充至视图中);6、DispatcherServlet 将页面响应给用户;

④、springBoot

框架相对于springMvc框架来说,更专注于开发微服务后台接口,不开发前端视图,同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对springmvc,大大简化了配置流程;采用maven的模块,在使用SPring就不需以传统的方式来用,只需要以maven导入对应的springboot模块,就能完成一大堆操作。简单的说,它使用maven的方式对Spring应用开发进行进一步封装和简化。

⑤、spring cloud

大部分的功能插件都是基于springBoot去实现的,springCloud更关注的是全局微服务的整合和管理,相当于管理多个springBoot框架的单体微服务,将多个springBoot单体微服务进行整合以及管理; springCloud依赖于springBoot开发,而springBoot可以独立开发;

2、介绍spring框架的组成

(1)、核心容器

一、Core Container:spring的核心容器,是启动spring的最基本的条件。Core Container由Beans、Core、Context和SpeL组成。1、Beans:负责创建类对象并且管理类对象,提供 BeanFactory,消除了编码式单例的必要性, 并且可以把配置和依赖从实际编码逻辑中解耦。对应的jar包spring-bean.版本号.RELEASE.jar。2、Core:核心类。对应的jar包spring-core.版本号.RELEASE.jar。3、Context:为Spring提供上下文信息,以一种类似于JNDI注册的方式访问对象。获取外部资源或者 管理注解。对应的jar包spring-context.版本号.RELEASE.jar。4、SpEL:提供了强大的表达式语言,用于在运行时查询和操作对象图。对应的jar包spring-expression.版本号.RELEASE.jar Beans和Core提供了框架的基本组成部分,包括 IoC 和依赖注入功能。Spring的核心容器是其他模块建立的基础,有spring-core、spring-beans、spring-context、spring-context-support和spring-expression(Spring表达式语言)等模块组成。

spring-core 模块:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。

spring-beans 模块:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。

spring-context 模块:建立在Core和Beans模块的基础之上,提供一个框架式的对象访问方式,是访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点。

spring-context-support 模块:支持整合第三方库到Spring应用程序上下文,特别是用于高速缓存(EhCache、JCache)和任务调度(CommonJ、Quartz)的支持。

Spring-expression 模块:提供了强大的表达式语言去支持运行时查询和操作对象图。

(2)、数据访问与集成模块由 spring-jdbc、spring-orm、spring-oxm、spring-jms 和 spring-tx 等 5 个模块组成。spring-jdbc 模块:提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析,用于简化JDBC。主要是提供 JDBC 模板方式、关系数据库对象化方式、 SimpleJdbc 方式、事务管理来简化 JDBC 编程,主要实现类是 JdbcTemplate、 SimpleJdbcTemplate 以及 NamedParameterJdbcTemplate。spring-orm 模块:是 ORM 框架支持模块,主要集成 Hibernate, Java Persistence API (JPA) 和Java Data Objects (JDO) 用于资源管理、数据访问对象(DAO)的实现和事务策略。spring-oxm 模块:主要提供一个抽象层以支撑 OXM(OXM 是 Object-to-XML-Mapping 的缩写,它是一个 O/M-mapper,将 java 对象映射成 XML 数据,或者将 XML 数据映射成 java 对象),例如: JAXB,Castor,XMLBeans,JiBX 和 XStream 等。

spring-jms模块(Java Messaging Service):指Java消息传递服务,包含用于生产和使用消息的功能。自Spring4.1以后,提供了与spring-messaging模块的集成。spring-tx 模块:事务模块,支持用于实现特殊接口和所有POJO(普通Java对象)类的编程和声明式事务管理。(3)、web springmvc由spring-websocket、spring-webmvc、spring-web、portlet和spring-webflux模块等 5 个模块组成。spring-websocket 模块:Spring4.0以后新增的模块,实现双工异步通讯协议,实现了WebSocket和SocketJS,提供Socket通信和web端的推送功能。spring-webmvc 模块:也称为Web-Servlet模块,包含用于web应用程序的Spring MVC和REST Web Services实现。Spring MVC框架提供了领域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成。spring-web 模块:提供了基本的Web开发集成功能,包括使用Servlet监听器初始化一个IOC容器以及Web应用上下文,自动载入WebApplicationContext特性的类,Struts集成类、文件上传的支持类、Filter类和大量辅助工具类。portlet 模块:实现web模块功能的聚合,类似于Servlet模块的功能,提供了Portlet环境下的MVC实现。spring-webflux 模块:是一个新的非堵塞函数式 Reactive Web 框架,可以用来建立异步的,非阻塞,事件驱动的服务,并且扩展性非常好。(4)、AOP 横向切面层由spring-aop、 spring-aspects 和 spring-instrument等 3 个模块组成。spring-aop 模块:是 Spring 的另一个核心模块,提供了一个符合 AOP 要求的面向切面的编程实现。作为继 OOP(面向对象编程)后,对程序员影响最大的编程思想之一, AOP 极大地开拓了人们对于编程的思路。在 Spring 中,以动态代理技术为基础,允许定义方法拦截器和切入点,将代码按照功能进行分离,以便干净地解耦。spring-aspects 模块:提供了与AspectJ的集成功能,AspectJ是一个功能强大且成熟的AOP框架。spring-instrument 模块:是 AOP 的一个支援模块,提供了类植入(Instrumentation)支持和类加载器的实现,可以在特定的应用服务器中使用。主要作用是在 JVM 启用时,生成一个代理类,程序员通过代理类在运行时修改类的字节,从而改变一个类的功能,实现 AOP 的功能。(5)、Test测试模块spring-test 测试模块。spring-test 模块主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。

3、说一下你对IOC的理解

DI(Dependency Injection)依赖注入: 指容器复制创建和维护对象之间的依赖关系,而不是通过对象本身复制自己的创建和解决自己的依赖。IOC控制反转: (Inversion of Control)即控制反转,在我们以往的编程中如果需要一个bean往往需要去手动去new一个出来。而spring帮我们解决了这个问题,在spring中我们只需要去定义bean,spring就会自动的帮我们实例化并管理Bean。而这些Bean就管理在spring容器中,控制反转是通过依赖注入实现的。

4.说一下你对AOP的理解

AOP是面向切面编程(横切逻辑编程),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。是面向对象编程(OOP)的一种增强模式,aop 是面向切面编程简单来说就是统一处理某一“切面”(类)的问题的编程思想,(比如事务管理、日志管理、权限控制等等)一个个切面,然后在运行的时候通过动态代理或者CGLib代理的方式织入到核心业务功能中。

①、应用场景AOP能做什么:事务管理、日志管理、性能测试、权限控制②、AOP的使用以及实现:一种是基于注解的方式,一种是基于XML配置文件的方式,spring的AOP的是实现:是通过动态代理模式来实现的(相当于中介解决问题加强)③、动态代理模式分为:(1)、jdk动态代理(类实现了接口)(2)、cglib动态代理(没有接口实现)

4、如何自定义一个AOP,实现切面?

先打注解@compent交给spring管理,打注解@aspect开启AOP 要在 Spring 中声明 AspectJ 切面, 只需要在 IOC 容器中将切面声明为 Bean 实例.–@Before: 前置通知, 在方法执行之前执行

–@After: 后置通知, 在方法执行之后执行

–@AfterRunning: 返回通知, 在方法返回结果之后执行

–@AfterThrowing: 异常通知, 在方法抛出异常之后

–@Around: 环绕通知, 围绕着方法执行

创建切面注解(包括切面类注解和切面方法注解,切点注解)2. 通过实现BeanPostProcessor处理有切面类注解的类,并解析切面方法为切面类放入缓存3. 处理有切点注解的bean,生成代理对象(jdk或cglib代理)4. 继承AbstractAutoProxyCreator重写wrapIfNecessary方法解决有循环依赖的bean,提前进行代理。 6、BeanFactory和ApplicationContext有什么区别,Spring的Bean懒加载和非懒加载有什么区别①、ApplicationContext是BeanFactory的子接口,功能更加强大(国际化,读取资源,邮件,模板),ApplicationContext在读取配置文件的时候就开始创建文件里配置的对象了称为;( ApplicationContext:迫切加载)

②、BeanFactory(使用的时候才创建文件配置的对象) 称为:(懒加载)

③、懒加载和非懒加载懒加载:对象使用的时候才去创建。节省资源,但是不利于提前发现错误;提前加载:容器启动时立马创建。消耗资源,但有利于提前发现错误Spring 默认设置是非懒加载

7、Spring的Bean被指定为singleton(生狗疼)以及proto type有什么区别? spring 支持几种 bean 的作用域?

singleton:单例模式, 当bean的scope为singleton时,Spring容器仅创建一个对象,当下次获取的时候还是第一次创建出来的对象,且获取的对象引用也相同。当使用 == 符号判断两个获取的对象时,得到的结果为true。

Prototype::原型模式当bean的scope为prototype是,Spring容器在用户获取该对象是创建一个新的对象。每次获取都创建一个全新的对象给用户操作。

spring 支持 5 种作用域,如下:· singleton:spring ioc 容器中只存在一个 bean 实例,bean 以单例模式存在,是系统默认值;· prototype:每次从容器调用 bean 时都会创建一个新的示例,既每次 getBean()相当于执行 new Bean()操作;· Web 环境下的作用域:· request:每次 http 请求都会创建一个 bean;· session:同一个 http session 共享一个 bean 实例;· global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。注意: 使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean 会带来很大的性能开销。

8、Spring的依赖注入方式以及实现的有哪些?

①、有4中注入方式:

1.Set方法注入:注入最简单,最常用的注入方式,支持注解+xml。

2.构造器注入:是指带有参数的构造函数注入,支持注解+xml

3.静态工厂的方式注入:通过调用静态工厂的方法来获取自己需要的对象,只支持xml。

4.实例工厂的方式注入:获取对象实例的方法不是静态的,所以需要new一个工厂类,再调用普通的实例方法,只支持xml。②、有两种实现方式:1.注解@Autowired(默认先通过名称,现通过类型来获取对象)@Resource (相反)@Required (默认先通过名称,现通过类型来获取对象)

2.配置文件(xml)

9、Spring的Bean的创建方式以及生命周期、bean的自动装配原理?(掌握)

创建方式:

1、交给spring管理创建2、静态工厂模式创建Bean3、非静态的工厂模式创建bean4.继承spring自带的工厂类(FactoryBean)创建beanspring中BeanFactory和FactoryBean的区别区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似

Bean生命周期:

①实例化 CreateBeanInstance:是指Spring通过反射获取Bean的构造方法进行实例化的过程。②属性赋值 PopulateBean③初始化 Initialization④销毁 Destruction

Spring Bean的自动装配原理:

自动装配是使用spring满足bean依赖的一种方法spring会在应用上下文中为某个bean寻找其依赖的bean。Spring中bean有三种装配机制,分别是:在xml中显式配置;在java中显式配置;隐式的bean发现机制和自动装配。

在SpringBoot的@SpringBootApplication注解中有一个注解@EnableAutoConfiguration,这个注解的功能就是实现自动装配的。他的作用主要是扫描导入每个jar中的spring.factory中的内容,然后把里面的内容读取到内存中,其实就是读取一堆的配置类。然后引入之后里面有些@Codictional的注解,根据特定的条件帮我们创建bean并注入,省去我们自己配置bean的过程,简化了开发步骤.标签选择器扫描jar包文件factory

10、springboot配置事务:

(1)、在处理事务的service业务层的类上打注解@Transactional 代表这个类里面的所有事务都是一组事务。打在方法上就代表是什么事务@Transactional (readOnly=true)代表查询事务就是默认开启,唯一可读

11、有哪些方式可以注册一个Bean到容器中

方式一、通过xml配置文件,例如:

①、在web.xml文件定位配置文件 classpath 路径②、启动tomcat 会加载web.xml文件 appliiction-context.xml

方式二、通过注解,例如@Controller、@Component、@Service,@Bean等

方式三、通过实现FactoryBean接口,例如

public interface FactoryBean {T getObject() throws Exception;Class getObjectType();boolean isSingleton();}// Samplepublic class PersonFactoryBean implements FactoryBean {….}

实现上述接口的3个方法,并把PersonFactoryBean注册到容器中,就可以把Person也注册到容器中。具体创建Person过程的源码可以看FactoryBeanRegistrySupport#getObjectFromFactoryBean方法。// 如下代码拿到的是Person对象applicationContext.getBean(“personFactoryBean”)

// 如果想要拿到PersonFactoryBean对象,可以再前面加&applicationContext.getBean(“&personFactoryBean”)

方式四、通过@Import注解用来批量注入bean:在导入外部包的时候,有大量的bean需要创建,@Bean一个一个添加是很麻烦的,这个时候就可以使用@Import注解,批量导入。

方式五、向BeanDefinitionRegistry 注册表中直接注册一个bean

12. 将一个类声明为Spring的Bean的注解有哪些?

Autowired :我们一般使用 @Autowired 注解自动装配 bean,要想把类标识成可用于 @Autowired注解自动装配的 bean 的类,采用以下注解可实现: @Component :通用的注解,可标注任意类为 Spring 组件。如果一个Bean不知道属于哪个层,可以使用@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。 @Service :对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。@Controller :对应 Spring MVC控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。

13. Spring的IOC启动原理

IOC :控制反转,把对象的创建,初始化,销毁等等工作都交给Spring管理,减少我们的工作量

一、配置文件的方式启动IOC:

1.加载配置文件: xml配置(ClassPathXmlApplicationContext),annot配置(AnnotationConfigApplicationContext)- 使用 ResourceLoader 加载xml配置文件,准备Environment环境对象2.注册Bean- 解析Xml , SAX解析,得到Document对象- 根据Document把Bean的定义封装成一个 BeanDefinition - 通过 BeanDefinitionRegistry 注册 BeanDefinition到Spring容器,存储到一个 ConcurrentHashMap中(DefaultListableBeanFactory)

3.创建实例- lazy = false : 注册好BeanDefinition的时候,就会根据BeanDefinition使用反射,创建Bean的实例,又存储到一个Map中缓存起来- lazy = true(默认) : 用到Bean的时候创建,applicationContext.getBean(User.class) , 就会先从Bean的缓存的Map获取,如果获取不到,就根据BeanDefinition使用反射创建一个Bean的实例,然后存储到Map中缓存起来,返回 (单例),如果是多例,每个获取都重新创建一个返回。

总结:1. 定义配置文件: application-context.xml / application-mvc.xml2.在web.xml定位 classpath:application-context.xml 3.启动tomcat 会加载web.xml中的配置,从而找到 application-context.xml 4.尝试解析 application-context.xml ,那Spring的IOC就开始了5.可以通过一个ClassPathXmlApplicationContext 去加载配置文件6.找到配置文件:new ClassPathXmlApplicationContext(“application-context.xml”)准备工作: 1. 准备 PathMatchingResourcePatternResolver ,2.准备环境对象 3.保存好配置文件地址刷新容器:7.加载配置文件: PathMatchingResourcePatternResolver implements ResourceLoader 加载xml配置文件8.解析配置文件:PathMatchingResourcePatternResolver : 路径匹配资源模式解析器 ,会通过Dom4j,SAX解析,9.把解析好的Bean的定义进行对象的封装BeanDefinition10.通过 BeanDefinitionRegistry.registerBeanDefinition 把 BeanDefinition注册到一个ConcurrentHashMap11.如果Bean的配置 lazy=”false” 那么就会根据BeanDefinition创建Bean的真正实例,缓存到一个HashMap12.如果执行applicationContext.getBean(MyBean.class) ?如果Bean是单例,检查缓存中有没有Bean,没有Bean从ConcurrentHashMap中取出对应的BeanDefinition,使用反射创建实例并缓存起来,如果缓存中有Bean,直接返回。如果不是单例,每次都会根据BeanDefinition使用反射重新创建要给Bean的实例返回

二、注解的方式启动IOC:AnnotationConfigApplicationContext 容器管理bean对象通过注解扫描,后续动作和上面一致。

14、Spring是如何管理事务的?

spring的事务管理三大接口:PlatformTransactionManager 事务管理器(通过datasources调用数据库的连接的对象connection,根据该对象开启数据库mysql的事务、管理事务、提交事务、回滚事务等),spring要管理事务,必须使用事务管理器,进行事务配置时,必须配置事务管理器,提交、管理事务。TransactionDefinition:事务详情(事务定义、事务属性),spring用于确定事务具体详情,例如:隔离级别、是否只读、超时时间,事务传播行为等进行事务配置时,必须配置详情。spring将配置项封装到该对象实例。TransactionStatus:事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。

管理事务的方式:方式一、半自动的方式 配置代理:在主配置文件中配置代理方式二、全自动XML方式(常用的方式)

方式三、注解全自动:在需要加上事务管理的类上加上@Transactional 注解,主类要开启事务注解,将会给类中的所有public方法加上事务管理。事务的实现是数据库层通过Spring AOP实现 里面柔和了service注解以及Transactional1、就是@Transactional(是通过动态代理)注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。2、方法必须是public修饰符。否则注解不会生效,不会报错,只是没卵用而已。3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强

(1)、在处理事务的service业务层的类上打注解@Transactional 代表这个类里面的所有事务都是一组事务。打在方法上就代表是什么事务,@Transactional (readOnly=true)代表查询事务就是默认开启,唯一可读

总结:首先打上注解开启事务管理器,spring管理事务都是基于数据库的,通过数据库的驱动去调用事务相关的sql语句去完成,用spring管理事务的时候,我们会把datasource交给他管理,TransactionManager 事务管理器(通过datasources调用数据库的连接的对象connection,根据该对象开启数据库mysql的事务、管理事务、提交事务、回滚事务等),而我们的事务都是作用于services层的相关的方法上的,spring将TransactionManager 事务管理器如何作用于事务相关的方法上呢?spring将事务的实现通过AOP思想横向切面编程实现的,AOP通过动态代理实现的,在事务相关的方法上打上标签@Transactional,spring会扫描到这些标签,spring会用动态代理模式代理掉我们的service,做一定的增强,在方法里面调用事务管理器执行相关的事务方法(柔和了service注解以及Transactional),进行事务提交,失败的话,走try cath事务报异常,就做事务的回滚.

15、Spring事务的回滚机制:

Spring的AOP即声明式事务管理默认是针对unchecked exception回滚。Spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtimeException)。

16. Spring用到了哪些设计模式

单例、工厂、适配者、代理、观察者、模板方法模式 、包装器设计模式单例设计模式 : Spring 中的 Bean 默认都是单例的。工厂设计模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。代理设计模式 : Spring AOP 功能的实现。Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。Spring AOP 已经集成了 AspectJ 。观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

17、RequestMapping 和 GetMapping区别? ①、@RequestMapping可以指定GET、POST请求方式②、@GetMapping用于将HTTP get请求映射到特定处理程序的方法注解具体来说,@GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。③、@PostMapping用于将HTTP post请求映射到特定处理程序的方法注解具体来说,@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。

18.SpringMVC怎么样设定重定向和转发的

一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理。如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理。(1)转发:在返回值前面加”forward:”,譬如”forward:user.do?name=method4”(2)重定向:在返回值前面加”redirect:”,譬如”redirect:http://www.baidu.com“

19.SpringMVC如何对时间格式的参数进行格式化?有哪些方式?

1). 在控制器中使用@InitBind注解 2). 在POJO(实体类)中日期属性上添加@DateTimeFormat

20.SpringMVC常用的注解有哪些 ?

①、@Controller:在SpringMVC中,controller主要负责处理前端控制器(DispatcherServlet )发过来的请求,经过业务逻辑层处理之后封装层一个model,并将其返回给view进行展示。@controller注解通常用于类上,如果结合Thymeleaf模板使用的话,会返回一个页面。如果是前后端分离的项目,则使用@RestController,表明返回的是json格式数据。

②、@RestController:= @Controller + @ResponseBody(注解是将返回的数据结构转换为 JSON 格式)

③、@RequestMapping@RequestMapping 是一个用来处理请求地址映射的注解,它可以用于类上,也可以用于方法上。用于类上的注解会将一个特定请求或者请求模式映射到一个控制器之上,表示类中的所有响应请求的方法都是以该地址作为父路径;方法的级别上注解表示进一步指定到处理方法的映射关系。

该注解有6个属性,一般在项目中比较常用的有三个属性:value、method 和 produces。value 属性:指定请求的实际地址,value 可以省略不写;method 属性:指定请求的类型,主要有 GET、PUT、POST、DELETE,默认为 GET。produces 属性:指定返回内容类型,如 produces = “application/json; ”。

④、@PathVariable(是从 URL 模板中获取参数值)@PathVariable 注解主要用来获取 URL 参数,Spring Boot 支持 Restfull 风格的 URL,比如一个 GET 请求携带一个参数 id,我们将 id 作为参数接收,可以使用 @PathVariable 注解

⑤、@RequestParam)(是从 Request 里获取参数值)@RequestParam 注解顾名思义,也是获取请求参数的,@PathValiable 注解也是获取请求参数的,⑥、@RequestBody(接受前端传过来的参数是一个对象)RequestBody 注解用于接收前端传来的实体,接收参数也是对应的实体,比如前端通过 JSON 提交传来两个参数 username 和 password,此时我们需要在后端封装一个实体来接收。在传递的参数比较多的情况下,使用 @RequestBody 接收会非常方便。

21.如何定义SpringMVC的拦截器

方式一、实现接口:①创建拦截器类实现HandlerInterceptor接口②配置拦截器配置文件

preHandle:拦截于请求刚进入时,进行判断,需要boolean返回值,如果返回true将继续执行,如果返回false,将不进行执行。一般用于登录校验。postHandle:拦截于方法成功返回后,视图渲染前,可以对modelAndView进行操作。afterCompletion:拦截于方法成功返回后,视图渲染前,可以进行成功返回的日志记录。

方式二、配置方式:在自己的springMVC.xml里面配置自己的拦截器

方式三、继承适配器:(继承 HandlerInterceptorAdapter 方式定义拦截器(实际上最终还是 HandlerInterceptor 接口实现)

重写这一个preHandle:拦截于请求刚进入时,进行判断,需要boolean返回值,如果返回true将继续执行,如果返回false,将不进行执行。一般用于登录校验。 22、过滤器和拦截器的区别?1 拦截器是基于java的反射机制的,而过滤器是基于函数回调。2 过滤器是servlet规范规定的,只能用于web程序中,而拦截器是在spring容器中,它不依赖servlet容器。3 过滤器可以拦截几乎所有的请求(包含对静态资源的请求),而拦截器只拦截action请求(不拦截静态资源请求)。4 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。5 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。6 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。7 拦截器是被包裹在过滤器之中。

23、HandlerInterceptor和HandlerInterceptorAdapter的区别?

相同:1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。3、性能监控:典型的是慢日志

不同:HandlerInterceptor(拦截器):HandlerInterceptor需要实现重写三个方法preHandle 、postHandle 、afterCompletion

HandlerInterceptorAdapter(拦截器适配器):HandlerInterceptorAdapter需要继承 重写一个方法preHandle

24.SpringMVC的执行原理

1、 用户发送请求至前端控制器DispatcherServlet。2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。4、 DispatcherServlet调用HandlerAdapter处理器适配器。5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。6、 Controller执行完成返回ModelAndView。7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。9、 ViewReslover解析后返回具体View。10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。11、 DispatcherServlet响应用户。

25.SpringMVC的Controller是单例还是多例,有没有并发安全问题,如何解决?

controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。正因为单例所以不是线程安全的(线程不安全)。解决方案:1、不要在controller中定义成员变量。2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。3、在Controller中使用ThreadLocal变量

26、SpringBoot有哪些优点?

框架相对于springMvc框架来说,更专注于开发微服务后台接口,不开发前端视图,同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对springmvc,大大简化了配置流程;采用maven的模块,在使用SPring就不需以传统的方式来用,只需要以maven导入对应的springboot模块,就能完成一大堆操作。简单的说,它使用maven的方式对Spring应用开发进行进一步封装和简化。

27、SpringBoot如何做全局异常处理?

一、为什么要用全局异常处理?

在日常开发中,为了处理出现很多的异常,不把异常抛给堆栈信息给前端页面,异常多了 try cath多了,代码耦合性较高,且不美观,不利于后期维护。为解决该问题,所以就将异常信息统一封装处理,更能区分Controller层方法返回给前端的String、Map、JSONObject、ModelAndView等结果数据的类型。

二,应用场景是什么?①、非常方便的去掉了try catch这类冗杂难看的代码,有利于代码的整洁和优雅。 ②、自定义参数校验时候全局异常处理会捕获异常,将该异常统一返回给前端,省略很多if else代码。③、当后端出现异常时,需要返回给前端一个友好的界面的时候就需要全局异常处理④、因为异常时层层向上抛出的,为了避免控制台打印一长串异常信息

三、如何进行全局异常捕获和处理?

方式一、Spring的AOP(较复杂) 方式二、@ControllerAdvice结合@ExceptionHandler(简单)(JSR303校验)在需要校验的类型的字段上打上@NotNull注解 @NotEmpty注解,在全局异常处理中 使用异常对象可以获取到BindingErrors 从而可以调用方法获取到所有校验未通过的字段及信息,自定义自己的状态码。

28、SpringBoot如何读取配置文件中的配置项?

对于 properties 文件的读取,采用 @PropertySource 、@Value 注解即可直接获取指定配置项。@Data : 用于提供 getter,setter。简化代码方式一、@PropertySource : 用于指定 properties 文件,需将 properties 文件放置在 能够获取到路径的地方@Component: 注入 bean ,不能省略,不然 @Value 注解不能获取到配置项方式二、Environment : 获取配置文件属性的接口方式三、ConfigurationProperties 方式获取

29、@SpringBootApplication标签的组成

是一个合成体,但其中最重要的三个注解分别是:三体结构 ”①、@SpringBootConfiguration:读取配置文件,配置文件的路径是当前根目录(src/main/resources/application.yml等)@Component:spring内置组件注解,用途是让spring容器扫描@Target(ElementType.TYPE) :用于描述注解的使用范围@Retention(RetentionPolicy.RUNTIME) :保留,指定保留时间,三个枚举,分别为source,class,runtime@Documented:可被javadoc等工具记录,注解类型信息会保存到生成的文档中@Inherited:个人认为是一个成员变量,父类被子类覆盖之后无法继承,子类中可以继承父类中未被覆盖的父类注解的值

②、@EnableAutoConfiguration:这个注解主要是继承@Configuration注解,这个我们就是为了加载配置文件用的;③、@ComponentScan:就是用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean.对应于XML配置形式中的 ,用于将一些标注了特定注解的bean定义批量采集注册到Spring的IoC容器之中,这些特定的注解大致包括:@Controller@Entity@Component@Service@Repository

30、.SpringBoot是如何整合SpringMVC的?SpringBoot是如何整合DataSource的?

1)、主类:@SpringBootApplication2)、开启自动配置:@EnableAutoConfiguration3)、导入EnableAutoConfiguration自动装配的选择器:@Import(AutoConfigurationImportSelector.class)4)、AutoConfigurationImportSelector.selectImports 选择加载自动配置的类的名字5)、SpringFactoriesLoader加载一些配置类,扫描classpath中的jar ,找到 META-INF/spring.factories(就是springboot的接口,存储需要自动装配的bean)

6)、spring-boot-2.0.5.RELEASE.jar里面的META-INF/spring.factories/EnableAutoConfiguration 配置项目后面的类7)、比如:HttpEncodingAutoConfiguration 编码过滤器的自动配置,以Bean的方式定义好了。比如;WebMvcAutoConfiguration 对SpringMVC的自动配置, InternalResourceViewResolver 视图解析器以Bean的方式注册好了 比如:DispatcherServletAutoConfiguration 就是针对于前端控制器的自动配置,以Bean的方式吧DispatcherServlet注册好了

比如:DataSourceAutoConfiguration针对于DataSource自动配置-> 通过DataSourceProperties加装yml配置-> DataSourceConfiguration.Generic.class 配置DataSource -> 如果没有定义DataSource,会自动创建一个DataSource(根据连接池的类型反射创建)-> 注册到容器。

31.SpringBoot的启动流程

1)、SpringApplication#run :开启秒表StopWatch计时2)、获取SpringApplicationRunListeners监听器3)、启动SpringApplicationRunListeners监听器4)、获取ApplicationArguments应用参数5)、获取环境:ConfigurableEnvironment ,这个环境对象中可以获取property6)、打印Bananer7)、创建上下文:ConfigurableApplicationContext(AnnotationConfigApplicationContext)8)、获取异常报告事件监听exceptionReporters 9)、准备上下文:prepareContext- ConfigurableEnvironment环境对象设置到容器中 - 初始化ApplicationContextInitializer - 注册:applicationArguments到容器 - 注册:Banner到容器10)、刷新上下文:refreshContext ,Spring和核心启动方法,注册Bean就在这里 - (invokeBeanFactoryPostProcessors 执行后置处理器)自动配置就着这执行的11)、刷新上下文后置工作:afterRefresh12)、执行 ApplicationRunListeners中的started(),发布 ApplicationStartedEvent 事件13)、执行Runner(ApplicationRunner和CommandLineRunner)

32.SpringBoot和SpringCloud的区别?

一、SpringBoot是什么?SpringBoot是一个快速开发的轻量级框架,帮助快速整合第三方常用框架,完全采用注解化(使用注解启动SpringMVC),简化XML配置,内置HTTP服务器(Tomcat、Jetty)。作用是简化Spring应用的初始搭建及开发,解决各种jar包版本冲突问题。

二、SpringCloud是什么?SpringCloud是一系列框架的有序集合,是一个分布式服务治理的框架,本身不会提供具体功能性的操作,是一个为开发者提供快速构建分布式系统的工具。简化了分布式系统基础设施的开发,包括服务发现、服务注册、配置中心、消息总线、负载均衡、断路器、数据监控等。

SpringCloud不是重复制造轮子,而是将目前各家公司开发的比较成熟的服务框架组合起来,通过SpringBoot风格进行再封装,屏蔽掉复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包,即默认大于配置;

三、SpringBoot和SpringCloud的联系?

SpringBoot+SpringCloud实现微服务开发。具体就是,SpringCloud具备微服务开发的核心技术:RPC远程调用技术;SpringBoot的web组件默认集成了SpringMVC,可以实现HTTP+JSON(Restfull)的轻量级传输,编写微服务接口,所以SpringCloud是依赖SpringBoot框架实现微服务开发。

四、SpringBoot和SpringCloud的区别?

1.SpringBoot专注于快速开发单个微服务,SpringCloud是将SpringBoot开发的一个个单体微服务整合并管理起来,它是关注全局的服务治理框架(RPC远程调用技术、服务治理等);

2.SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系。

33、SpringCloud常用组件和作用?

(1)、服务注册与发现——Netflix Eureka硬编码服务提供者地址的方式有不少问题。要想解决这些问题,服务消费者需要一个强大的服务发现机制,服务消费者使用这种机制获取服务提供者的网络信息。不仅如此,即使服务提供者的网络地址发生变化,服务消费者也无须修改配置文件。(2)、客户端负载均衡——Netflix Ribbon 1、Ribbon 的作用是负载均衡,会帮你在每次请求时选择一台服务器,均匀的把请求分发到各个服务器上。2、Ribbon负载均衡策略:(随机、轮询、权重、地区、响应)在配置类上加上一个IRule上加上一个@bean

(3)、服务接口调用——Netflix Feign(解决服务负载均衡调用的Feign 底层就是Ribbon)——集成在客户端)——解决Ribbon负载均衡中的请求的字符串拼接

1、Feign Client 会在底层根据你的注解,跟你指定的服务建立连接、构造请求、发起请求、获取响应、解析响应,等等。2、Feign负载均衡步骤

(4)、服务熔断器——Netflix Hystrix ((豪猪)熔断器-服务保护保证服务健壮性——集成在服务提供端)

降级:请求一个服务出现了异常(报错,超时,熔断,限流)会触发降级,返回事先准备好的兜底数据- 熔断:一个服务多次访问失败,这个服务会被标记为熔断(短路)状态,被熔断的服务如果有其他服务来请求它,快速失败,触发降级,不要等待。- 限流:限制请求的并发量服务链上,因为某个微服务的异常,而导致雪崩效应,整条服务链宕机的问题;Hystrix回去捕获这个异常,利用Hystrix接口处理这类异常。1、Hystrix熔断器如何做熔断与解决雪崩的?①、资源隔离线程池隔离 :(线程池隔离和请求线程不是同一个线程信号量隔离 :信号量和请求线程是同一个线程)②.熔断当错误到达一定阈值 熔断 每个一段时间 进入半熔断状态 允许少量请求进入 如果成功闭合如果失败 继续熔断③.降级针对一些不是特别重要的业务不影响整个流程的业务 可以在隔离和熔断后进行一些托底数据的返回④、缓存:提供了请求缓存、请求合并实现。

(5)、服务网关——Netflix Zuul负责网络路由,可以做统一的降级、限流、认证授权、安全,等等。

(6)、服务跟踪——Netflix Sleuth(7)、聚合Hystrix监控数据——Netflix Turbine(8)、分布式配置——Spring Cloud Config

常用组件:①、EurekaEureka是微服务架构中的注册中心,专门负责服务的注册与发现;每个微服务中都有一个Euraka client组件,专门负责将这个服务的服务id(serviceId)、ip、端口等信息注册到Eureka server中;Euraka Server是一个注册中心,该组件内部维护了一个注册表,保存了各个服务所在的机器ip和端口号等信息。②、FeignFeign主要负责与其他服务建立连接,构造请求,发起请求,获取响应等等,用来远程调用其他的服务;Feign使用Jdk的动态代理来针对FeignClient注解修饰的接口创建动态代理;调用FeignClient注解修饰的接口,实际是调用Feign创建出来的动态代理;根据RequestMapping等注解信息,动态构造出要请求的服务地址;针对该构造出来的地址,发起请求,解析响应;③、RibbonRibbon主要负责负载均衡,针对每次请求,Ribbon会从Euraka client服务列表中选择一个服务发起请求,均匀的把请求分发到各个服务中;默认使用的是Round Robin轮询算法;Feign使用Ribbon去获取服务信息,例如服务的ip、端口等信息,然后针对服务的信息构造并发起请求。Ribbon的主要组件与工作流程Ribbon的主要组件:Ribbon的核心组件(均为接口类型)有以下几个:ServerList 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

ServerListFilter 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

IRule 选择一个最终的服务地址作为LB结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。Ribbon的工作流程:Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

④、Hystrix微服务架构中,存在着恐怖的服务雪崩问题,也是当服务直接互相调用,如果其中某个服务挂掉了,会导致其他服务不可用,甚至导致其他服务也挂掉了;Hystrix是隔离、熔断以及降级的一个框架;Hystrix默认是通过线程池技术对服务进行隔离,每个微服务对应一个线程池,对每个服务进行调用时,都是通过在自己的线程池中调用;如果某个服务挂了,hystrix就直接返回,这个过程就是熔断;如果某个服务挂了,hystrix就执行一个默认的方法逻辑,这个过程就是降级;⑤、ZuulZuul是微服务的网关,这个组件是负责网络的路由;所有请求都往网关走,网关会根据请求中的特征,将请求转发给后端的各个服务;

⑥、config 配置中心

34.Eureka心跳和服务剔除机制是什么

Eureka心跳机制:客户端每30秒发送一个心跳,询问是否还在。

Eureka服务剔除机制:当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。

Eureka自我保护机制:在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。

35.Eureka的服务注册与发现的工作流程

Eureka注册中心工作原理(服务注册,发现,续约,下线)1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息,服务提供者在启动的时候需要向注册中心注册自己的信息,而注册中心把向自己注册的服务提供者都保存下来,以便服务消费者获取用来发起请求,而服务消费者需要从注册中心获取服务提供者列表,然后向服务提供者发起调用。

2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务

3、而服务消费者向注册中心获取服务提供者列表有两种方式:1、消费者主动向注册中心拉取;2、注册中心主动给服务消费者推送。其实,服务提供者注册完自己之后还会和注册中心保持心跳,以此来证明自己还能正常提供服务。这样上面说到的那些情况无论动态感知上下线还是负载均衡,都不需要人为的去操作了,这些都交给服务自己去完成。这样就达到了服务解耦的作用。

5、eureka的主要角色分为服务端(server)和客户端(client);(1)、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常;(2)、Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例,而服务提供者会向server注册、注销、续约(默认30s,超过90s不续约将被注册中心剔除)、以及获取服务列表(客户端会缓存获取下来的列表);单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端;当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式;

5、然后向服务提供者发起远程调用;(1)、服务调用时,服务消费者会向注册中心获取服务列表,会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存,Eureka Client 获取到目标服务器信息,发起服务调用6、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除

36.对于CAP理论,Eureka选择的是AP还是CP?它保证了一致性还是可用性?

1.CAP指的是一致性(Consistency),可用性(Availability),分区容错性(Partition tolerance),在分布式中,网络是不可控的,所以首先要保证 P ,然后在A和C之间做选择。要么AP ,要么CP 。

2.Eureak选择AP 保证了可用性降低了一致性, Nacos 默认 AP ,可以 CP和AP可以切换, Zookeeper 就是 CP ; Redis AP

37.说下Ribbon和Feign的区别呢?

Ribbon添加maven依赖 spring-starter-ribbon 使用@RibbonClient(value=”服务名称”) 使用RestTemplate调用远程服务对应的方法feign添加maven依赖 spring-starter-feign 服务提供方提供对外接口 调用方使用 在接口上使用@FeignClient(“指定服务名”)

Ribbon和Feign的区别:Ribbon和Feign都是用于调用其他服务的,不过方式不同。1.启动类使用的注解不同,Ribbon用的是@RibbonClient,Feign用的是@EnableFeignClients。2.服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。3.调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。 Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。

38.一个请求过来,在你们的微服务项目中经过哪些流程?

(1)、一个前端的界面入口普通链接(调用微服务)(2)、请求来到Nginx(配置访问转发到的地址,这里是gateway或者zuul、系统的唯一入口网关)(3)、网关(gateway、zuul) routes路由配置(4)、Eureka上找到服务,访问到服务

39、如何实现Eureka的高可用集群?

防止单点故障配置文件yml里面配置相关的信息,对Eureka进行集群,各个Eureka进行注册。1.配置环境名:profiles2.服务名3.eureka主机4.ip注册5.实例ID、6.端口

40、Hystrix的限流有几种方式,有什么区别?

两种方式:线程池隔离 :(线程池隔离和请求线程不是同一个线程) 执行流程:使用一个线程池来限制请求的数量,一个请求过来分配一个线程去执行,如果没有线程分配了,进入排队,线程没有了也没有排队了,请求被拒绝,触发降级最大并发:线程数+排队数是否异步:是性能开销:线程切换开销

信号量隔离 :信号量和请求线程是同一个线程)执行流程:通过一个信号量(数字)来限制请求的数量,一个请求过来,计数器+1,走一个请求计数器-1,如果计数器达到信号量,请求直接拒绝,触发降级 最大并发:信号量是否异步:否性能开销:没有线程切换开销

缓存:对请求做缓存,提高并发请求的效率

**二者区别:信号量、线程池。两者最大的区别就是信号量只做限流,不会另外开启线程去执行任务。而线程池则是线程耗尽,队列满的情况 下进行限流。

41.Hystrix的熔断有几种状态?这几种状态是怎么变换的?

熔断状态机3个状态:Closed:关闭状态,所有请求都正常访问。Open:打开状态,所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会完全关闭断路器,否则继续保持打开,再次进行休眠计时这几种状态是怎么变换的:

当错误到达一定阈值 进入熔断每个一段时间 进入半熔断状态 允许少量请求进入 如果成功进入闭合状态如果失败 继续熔断

42、服务A使用ribbon调用服务B,Ribbon是如何工作的? 发送请求,被LoadBalancerInterceptor拦截器拦截,请求被交给ribbon来处理拦截器拦截请求,交给了RibbonLoadBalancerClient的execute方法(下面的逻辑都是包含在这个方法中)在进行负载均衡之前首先得知道有哪些服务实例信息,所以通过DynamicServerListLoadBalancer的updateListOfServers方法从注册中心(Eureka)那里获取到了所有的服务实例信息,并且会定时更新使用负载均衡算法(默认轮询算法)从所有的服务实例信息中选择一台机器出来将请求发送给负载均衡选择出来的服务实例上去

43、为什么Feign的接口可以直接注入进来用?

Spring低层对 fegin进行了整合启动类:spring启动的时候就开启对fegin加载扫描 Fegin的接口打上注解 类似交给spring管理 @EnableFeignClients(“cn.hemaming.hrm.client”)@FeignClient(_value = “auth-service” ,fallbackFactory = AuthClientFallback.class)_

44、Ribbon的负载均衡算法有哪些?

地区轮询:RoundRobinRule:默认轮询的方式随机:RandomRule:随机方式权重、响应WeightedResponseTimeRule:根据响应时间来分配权重的方式,响应的越快,分配的值越大。BestAvailableRule:选择并发量最小的方式RetryRule:在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的serverZoneAvoidanceRule:根据性能和可用性来选择。AvailabilityFilteringRule:过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)

45、Zuul有哪几类Filter,他们的执行顺序是怎么样的?

1)pre可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程。

2)route在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。

3)post在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。

4)error处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。

前置路由——》后置——》返回数据给前端。前置报错——》走异常——》走后置后置报错——》走异常直接结束

46. 在Zuul中做登录检查如何实现?

写一个前置拦截器,对所有的资源路径进行拦截,放行登录的路径,当访问某一资源路径时,进行登录拦截检查,看是否有登录的携带token47.在Zuul中如何做限流?写一个拦截器,在zuul配置文件里面限定最大的访问量。通过令牌桶算法从单个服务的角度实现限流,原理:利用redis键过期的自动删除的特性。以url为key,如果key不存在,创建key,并设置键过期时间,相同请求过来就对这个key进行计数,使用redis.incr原子方法,当请求超过limit时,则不让请求api。

47、EurekaClient拉取注册表&心跳续约用到了什么技术来实现?

创建的一个 ScheduledExecutorService线程池+定时任务,可以进行定时或周期性的工作调度服务。

48、Springcloud分布式SpringSecurity项目授权、鉴权流程

一、微服务授权认证方式:

1、微服务授权常见方案

1、CAS单点登录:登录一个相同的服务,其他的服务都可以访问,是基于cookion实现单点登录的流程:单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分。单点登录sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理

1,当用户访问保护资源,验证是没有登录,会跳转到SSO认证中心2,SSO认证中心发现用户未登录,将用户引导至登录页面;3,输入账号和密码提交登录。4,SSO认证中心校验用户信息,创建用户和SSO认证中心的全局会话,同时创建授权令牌5,SSO带着令牌去跳转到受保护的系统6,系统去SSO认证中心效验令牌,如果有效就注册系统,并使用该令牌创建用户的剧部会话

2、分布式会话(session)+网关+redis优点:简单好实用缺点:redis的安全性流程:3、客户端Token+网关优点:服务端不用存储token缺点:token太长了流程:4、客户端 Token 与 API 网关结合这个方案意味着所有请求都通过网关,从而有效地隐藏了微服务。在请求时,网关将原始用户令牌转换为内部会话 ID 令牌。在这种情况下,注销就不是问题,因为网关可以在注销时撤销用户的令牌。

二、微服务分布式项目采取:

方式一:客户端Token+zuul+SpringSecurity+SpringCloud+Oauth2+JWT解释:² 客户端 : web端,移动端,三方程序² 认证服务:负责认证逻辑(登录)和颁发令牌(token)等² 网关:负责token统一校验和统一授权² 资源服务:负责授权(用户对资源的访问权限检查)和返回资源

方式二、Token+SpringSecurity+Oauth2+JWT不使用网关授权

三、微服务项目认证授权怎么实现的?

方案、Token+SpringSecurity+Oauth2+JWT不使用网关授权OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。

JWT(json+web+token)相当于就是token JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。

SpringSecurity认证流程

² 请求过来会被过滤器链中的UsernamePasswordAuthenticationFilter拦截到,请求中的用户名和密码被封装成UsernamePasswordAuthenticationToken(Authentication的实现类)² 过滤器将UsernamePasswordAuthenticationToken提交给认证管理器(AuthenticationManager)进行认证.² AuthenticationManager委托AuthenticationProvider(DaoAuthenticationProvider)进行认证,AuthenticationProvider通过调用UserDetailsService获取到数据库中存储的用户信息(UserDetails),然后调用passwordEncoder密码编码器对UsernamePasswordAuthenticationToken中的密码和UserDetails中的密码进行比较² AuthenticationProvider认证成功后封装Authentication并设置好用户的信息(用户名,密码,权限等)返回² Authentication被返回到UsernamePasswordAuthenticationFilter,通过调用SecurityContextHolder工具把Authentication封装成SecurityContext中存储起来。然后UsernamePasswordAuthenticationFilter调用AuthenticationSuccessHandler.onAuthenticationSuccess做认证成功后续处理操作² 最后SecurityContextPersistenceFilter通过SecurityContextHolder.getContext()获取到SecurityContext对象然后调用SecurityContextRepository将SecurityContext存储起来,然后调用SecurityContextHolder.clearContext方法清理SecurityContext。注意:SecurityContext是一个和当前线程绑定的工具,在代码的任何地方都可以通过SecurityContextHolder.getContext()获取到登陆信息。

四、常见的权限框架有

1,Shiro 框架Java的一个安全框架;对比Spring Security,可能没有Spring Security做的功能强大2,spring Security一个轻量级的安全框架,它确保基于Spring的应用程序提供身份验证和授权支持

关于项目

一、单体项目:

(1)、概念

1 前后端分离的理解

项目前后端开发:(1)、前后未端分离前后端开发都在同一个项目中,共同开发(2)、前后半端分离前后端开发都在同一个项目中,相互开发,分工不同(3)、前后端分离a、前后台的项目是不同的项目,b、前后台都独立开发,独立部署,c、不同的访问地址,不同的端口号(不同的服务器)(4)、前后端分离后测试相关功能的数据来源:a、前端使用的是mockjs 模拟数据测试b、后端使用的是postman 测试接口(接口:controller —>数据接口)c、后端与前端进行连接 swagger(自动生成文档)

2 前端怎么独立开发?

我们采用的是Element,element是一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库,提供了很多的ui组件。我们可以使用这些组件快速开发前端项目。

3 swagger是什么?

swagger是接口规范。接口测试人员和前段开发人员要通过接口描述测试接口,所以需要定义一个接口规范。swagger可以直接罗列所有接口,每个接口有访问地址(访问方式),参数及返回值.可以直接通过后端代码产生能够让前台开发或测试人员能够看懂的接口文档。

4 交互方式

在前后端分离架构中,后端只需要负责按照约定的数据格式向前端提供可调用的API服务即可。前后端之间通过HTTP请求进行交互,前端获取到数据后,进行页面的组装和渲染,页面跳转,最终返回给浏览器。

5 后端如何进行接口测试?

采用了一个postman工具。postman就是一个http协议接口测试工具,可以来发送各种http请求,可以用它来测试http协议接口.

(2)、Redis

1 为什么使用redis?

Redis 是一个使用 C 语言开发的key-value形式的高速缓存nosql数据库。它先存到内存中,然后会根据一定的策略持久化到磁盘,即使断电也不会丢失数据。另外它支持较多的数据类型,可以应用到多个场景。比如;记录帖子点赞数、点击数、评论数;缓存近期热帖;缓存文章详情信息;记录用户会话信息。

2 redis的持久化机制。

redis的持久化其实就是把数据放到磁盘里面,让我们的数据可以一直存在,即使断电也不会造成数据丢失。Redis 的持久化有两种方式,或者说有两种策略:RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。

3 redis支持的数据类型。

string(字符串)、list(列表)、hash(字典)、set(集合)、zset(有序集合)。

(3)、注册

1 注册是怎么做的?

注册包括手机注册和邮箱注册,逻辑都是一样的,只是激活方式不一样。大致流程都是:①用户在页面输入手机号/邮箱之后,点击获取验证码。②后台生成验证码,并将验证码存入redis。(如果问为什么用redis?回答redis的优点就可以了)③然后调用发送短信/邮件接口,将验证码发送到收件/邮箱。④用户收到验证码,输入页面,点击注册。后端注册接口要比较用户输入的验证码与redis中存入的验证码比较。如果一致继续下一步,如果失败返回验证码失败,让用户重新输入。

2 密码是怎么处理的?

密码采用了md5加密的方式再存入数据库,因为md5是不可逆的,更安全。

(4)、登录

1 用户和管理员登录是分开写的吗?

用户和管理员登录是同一个接口,通过前端传过来的type判断是用户还是管理员,然后跳转不同的页面。

2 登录这块的表设计是怎么样的?

用户是一张表,管理员是一张表,然后我们还做了一个登录表,登录表里面是所有用户和管理员的登录账号和密码,因为管理员也可以登录我们的网站享受服务,所以有可能一个手机或邮箱既是用户又是管理员。为了区分这种登录账号到底是要登录到后台还是网站,所以我们登录表里面有一个type字段,区分该账号到底是用户还是管理员。

3 怎么判断用户是否登录?

登录成功,用uuid生成了一个随机数,将该随机数作为key,用户信息作为value存入redis,然后传到前端,前台取名为token会将它放到localStorage里面,并且我们在每次发起请求到后台时,都会在请求头中放入该token,在后台的拦截器中,我们会获取每一个请求的token,如果没有token或者通过该token在redis中没有获取到相应的用户信息,我们都认为它没有登录,然后返回前台,否则就放行该请求。

4 前端发起的所有的请求都会被拦截吗?

除了登录和注册接口,其他的会被拦截,如果登录和注册也被拦截的话,那么程序也就进行不下去了。

5 是如何让所有的请求都携带token的?

通过axios前置拦截器,在所有请求发起前,判断token是否存在,如果存在就在请求的header中加入token。

二、微服务项目:

1、你们项目是如何做服务降级的?

比如,当我们调用数据库获取商品信息时,发现mysql挂了,这时调用肯定会报错,报错就会执行备选方法:getFallback().我们就可以在getFallback里去获取缓存的商品信息部分数据返给上游,完成降级工作。报错,超时,reject,熔断,都会走降级方法。

2、分布式项目是如何保证接口的幂等性的?

1、每个请求必须有一个唯一的标识,比如每个订单支付请求都包含订单 id,订单id是唯一的,且每个订单只能支付一次。2、每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录这个订单的支付流水。3、每次接收请求需要进行判断,判断之前是否处理过。如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,如果 orderId 已经存在,唯一键约束生效,报错,插入失败,那么就不用再扣款了。

3、用过redis吗?为什么要用?怎么用

在上传项目中对商品类型进行缓存,商品类型是使用比较频繁但是数据又不是经常变得,所有适合方法缓存,并且我们商品服务是要做集群。所以不能使用普通的二级缓存。要使用redis来作为中央缓存。引申1:你们商品怎么做集群的。开多个服务器,每个都部署商品服务器。客户端通过Eureka会完成负载均衡调用。引申2:redis和db是怎么同步的引申3:怎么防止缓存穿透?正在增删改数据库数据,突然访问缓存?—自己去查

4、 用过ES没有?哪儿用的?为什么要用?怎么用?

在我最近的这个项目中有使用到全文检索。我使用的是是海量全文检索引擎是ElasticSearch。ES是一个分布式,可扩展,近时间的搜索与数据分析引擎。里面的商品模块因为有大量的商品数据。抛弃了数据库,选用了ES。

在商品模块用的,用户需要高并发搜索商品信息。如果每次都到数据查询,效率非常低,我们可以使用基于索引的全文检索替换数据库查询。并且商品模块是做了集群了的,不能使用lucene工具包,要使用搜索服务器,我们用哪个的是ES。

具体做法是:在管理员添加商品时只是添加到数据库,用户查询不到。当对商品进行上架时才添加到索引库,这时用户才能查询当对商品进行下架是,需要删除索引库里面的数据当然对于已经上架的商品做删除和修改时要做同步操作。

为什么用1. Sql语句是处理不了非结构化的数据的。2. 模糊查询效率低3. 文本数据中没有相关排序4. 没有摘要截取5. 查询效果不好6. 关键字没有高亮我用的ES相比较其他的全文检索工具具有分布式和易安装的特点。{luncene(全部检索工具包 es就是基于它实现的,Solr的分布式需要借助第三方来实现)}es对比上面更加简单。怎么用需要安装 ES服务器,必要时也需要安装kibana客服端

扩展(为什么用。详细解释)

生活中我们的数据可分为两类,一类是结构化数据,一类是非结构化数据。结构化数据:也称为行数据,是有二维表数据结构来逻辑表达和实现数据。主要通过关系行数据库来存储和管理的。非结构化数据:又称为全文数据,不定长或无固定格式,包含办公文档,xml,html, word文档,图片,音频等。根据不同数据的分类搜索也可分两种:结构化数据一般通过关系型数据库的二维表(table)的方式来存储和搜索,也可建立索引(这里我们要知道索引的优缺点)非结构化数据也是全面数据搜索的主要两种方法,顺序扫描和全文检索顺序扫描:通过文字名称了解大概的搜索方式(比如在一张报纸找到“java”需要从头到尾阅读报纸然后标准出现的位置,无疑效率很慢)全文检索:把部分非结构化的数据想办法想弄得有结构化(索引)。这就是全文检索的基本思路。这种方式的主要工作量在前期索引的创建,但后期搜索却很高效。

6、有没有做过页面静态化?为什么要使用?怎么使用

页面并发高,页面内容不怎么变,可以考虑做页面静态化

在商城主页和商品详情时使用,因为他们都是要频繁访问。并且在一定情况下都是不可变的。所以可以使用模板技术吧他们生成静态页面。如果数据发生变化后,要重新生成静态页面

单体项目:使用模板引擎(freemarker) 把页面生成html,访问的时候直接返回html,不在需要重新查询数据渲染视图。原理就是:使用模板引擎(freemarker)将页面需要的数据,和模板事先进行合并,生成一个html 。

课程详情静态化后台课程列表,增加一个“页面静态化”按钮2. 编写页面静态化逻辑(1) 事先准备好页面的模板:webapps/templates/course_detail.ftl(2) 查询页面所需要的数据(3) 使用模板引擎合并模板生成html : course_detail_110.html(4) 把html保存到项目中的某个位置 webapps/views/course_detail_110.html(5) 把html路径和当前课程数据绑定3. 在门户课程列表点击的超链接指定为 /views/course_detail_110.html即可

注意:如果做了前后端分离,页面静态化逻辑一样,但是html就不能输出到后端项目中,而是应该自动输出到前端的服务器对应的部署目录中,如: Nginx/html

分布式理解页面静态化需要生成静态页面的模块提前准备好模版 将数据从数据库中查出来存到redis 然后从redis从取出数据和模版结合生成html 上传到oss 会得到一个回调地址然后发送消息队列 然后前端服务项目监听该队列获得地址并下载html 去覆盖原来的html文件

扩展1:主页生成静态页面时机 -自己写扩展2:详情页生成静态页时机 -自己写

6、有没有做做过数据库相关的优化?在哪儿做?为什么要做

做过,在做商城时,对商品和sku做了垂直分表,把商品大字段并且放到商品详情表,通过外键进行关联。对sku做垂直分表,在查询商品项目时,其他信息都是暂时不可变的,只有库存是经常变的,所以把库存单独放一张表,这样以后查询库存时就不需要查询额外信息。对商品表做了反3NF,一些信息是可以到其他表查询,但是为了提供效率在自身放了一个冗余字段。

7、 有没有用过对象存储(分布式文件系统)?哪儿用?为什么要用?

在商城项目中,使用fastdfs分布式文件系统,对项目中的图片进行统一处理。这样在集群环境也能使用,并且由于以后访问图片都到图片服务器,所以降低了web服务压力。

8、你的商城项目用户量多大?你觉得用分布式架构合理吗?

我们项目据项目经理说是按照千万级别用户量来考虑的,目前用户量不大,但是还是要考虑未来的拓展问题. 分布式架构虽然开发上复杂度上有一些增加,但是未来做大了拓展方便,我觉的也是很值得的

9、你这个商城用了多少个数据库?

数据库我们暂时分了三个商品,用户的订单相关的,主要是方便拓展,但是又不想过多涉及分布式事务,就把订单,积分,优惠券相关的都放在一个数据了(分布式事务不要过多提及,如果问到就说是经理写的,我们只需要调用相应的方法就行了)

10、你们怎么分库分表的?

答案一:可以使用开源的数据库中间件mycat,需要按照对应的业务规则来分片。这个问题建议先看看相关资料,然后再答,如果没有把握就讲是项目经理弄的。(一般做了分库之后,查询是很少使用join的,因为是会涉及到跨库的join,性能较低)答案2:我们的分库分表是项目经理搞的,我也大概了解过,主要是按照业务来进行划分,但是考虑到我们业务并没有那么大就没有划分太多数据库,分表方面是把商品,商品详情,商品图片这些大表拆分成了小表优化性能,并没有使用MyCat之类的中间件(MayCat之类的中间件我们最好回避,不要说是自己负责的)

11、订单你处理过的并发量有多大?

我们项目初期阶段的的设计目标是1000(或者两千)的并发,目前用户量还没有上来,所以并发量并没有太高, 测试那边说目前并发1000情况下支撑1000QPS问题不大,用户量大了我们随时扩容就行

12、第三方支付怎么做的

支付这块我们接入了支付宝和微信两中支付方式,我负责了一部分支付宝的支付流程.微信的大概看了一遍,也都差不多的流程吧! 支付宝这边是调用支付宝SDK的支付接口(假设我们项目是只有APP,没有PC端), 如果用户手机安装的有支付宝就会拉起支付宝程序进行支付,如果用户手机没有没有安装支付宝,就会跳转到支付宝网页端要求用户输入用户名/密码进行支付, 支付之后支付宝会异步调用我们指定的接口通知支付结果, 我们根据支付结果是成功还是失败来执行相应的业务逻辑. 业务逻辑主要是更改订单状态,更改支付单状态,增加相应积分,发放相应优惠券之类的业务, 业务逻辑稍微复杂一些. 主要是涉及到金钱的业务必须非常严谨,需要考虑到各种情况,并且详细的记录日志,保证就算出了问题也能够根据相应的记录或者日志恢复数据PS: 还有一个就是涉及到分布式事务, 因为订单支付成功之后会去商品库修改订单状态和支付单状态,同时在支付数据库插入相关表,这就涉及到分布式事务问题,这种问题尽量回避,就说我们就是调用经理写好的接口就行了. 如果对分布式事务了解过的同学可以简单说下对分布式事务的理解,但是不宜过深入

13、你项目中是怎么实现单点登录的?

单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分。单点登录sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理

7,当用户访问保护资源,验证是没有登录,会跳转到SSO认证中心8,SSO认证中心发现用户未登录,将用户引导至登录页面;9,输入账号和密码提交登录。10,SSO认证中心校验用户信息,创建用户和SSO认证中心的全局会话,同时创建授权令牌11,SSO带着令牌去跳转到受保护的系统12,系统去SSO认证中心效验令牌,如果有效就注册系统,并使用该令牌创建用户的剧部会话

秒杀总结:

一、商城商品秒杀三大难点

高并发、高性能、一致性

二、秒杀商品流程:

1.秒杀商品发布2.秒杀商品展示3.执行商品秒杀4.秒杀下单5.支付订单6.商品发货

三、秒杀业务实现流程

1.秒杀商品发布(1)、设置秒杀的时间范围(2)、设置秒杀的课程编号,即同一个课程可以参加多场秒杀活动,根据唯一的编号判断是那一场秒杀的课程。(3)、设置秒杀的课程数量(4)、使用cron表达式设置一个定时任务,即每天凌晨1点查询当天的课程,对当天参与秒杀的课程进行发布。(5)、判断秒杀的课程是否已经发布(6)、设置秒杀随机码(7)、库存预热——使用redis信号量把库存预热到redis中,执行秒杀的时候就从redis里面减库存,不需要操作数据库,这样可以提高秒杀的速度。(8)、存储到redis中2.秒杀商品展示(1)、从redis中根据查找出每个时间段秒杀的商品(2)、未到时间先禁用秒杀按钮(3)、对秒杀地址进行加密,避免有人不停的刷秒杀接口3.执行商品秒杀(1)、判断用户是否登录(2)、判断秒杀码、秒杀课程是否存在(3)、避免有人刷接口,所以需要再判断秒杀码、秒杀的课程、秒杀时间是否有效(4)、判断库存,预减库存(5)、创建订单(6)、向rabbitMQ发送订单消息(7)、将秒杀结果返回给用户4.秒杀下单(1)、订单服务监听MQ消息,收到消息后,直接从MQ中获取订单信息(2)、创建订单并保存到数据库(3)、创建订单详情并保存到数据库(4)、将订单信息保存到redis中,用来做订单支付(5)、下单成功后将订单信息存放到延迟队列(6)、手动消费消息(7)、设置订单支付有效期,超过时间之后就使用死信交换机将消息放入到死信队列中(8)、订单服务监听死信队列中的订单消息,判断死信队列中的订单是否支付(9)、死信队列中的订单未支付就进行退库操作,然后将库存存储到redis中(10)、更新数据库支付状态和订单状态5.支付订单(1)、集成支付宝(2)、支付申请(3)、保存支付记录,支付状态为待支付——无论支付成功还是失败都需要保存,成功之后修改支付状态(4)、根据订单号查询订单(5)、判断订单是否有效(6)、调用支付宝接口进行支付(7)、支付完成后调用异步接口,修改支付状态为已支付。将用户的id和课程id进行绑定。将订单号和支付结果发送到MQ中。订单服务监听支付结果修改订单状态(8)、调用同步接口提示支付成功

四、秒杀功能的优化

(1)、前端优化

页面静态化将秒杀界面静态化,因为这个页面的大多数数据都是固定不变的,可以将静态资源部署到ngnix实现动静分离CDN加速将静态页面缓存起来,客户端就可以从最近的cdn服务器节获取静态资源,加快响应速度前端限流点击秒杀后就禁用按钮,或者增加图片验证码等延迟时间的方式流量错峰加入图片验证码等等

(2)、后端优化

链接加密链接不能被暴露,防止有人通过其他方式通过获取到的秒杀地址不停的刷秒杀接口。可以将地址进行MD5加密恶意拦截对恶意的请求进行拦截操作后端限流sentinel和hystrix限流服务隔离将秒杀单独集成一个服务库存预热预减库存或者是下单减库存可以将商品的库存量存到redis里面,每次秒杀的时候就去查看redis里面的库存,然后从redis里面减库存。但是并发特别高的时候,建议对redis集群数据缓存将秒杀课程存储到redis里面,从redis里面进行查询和操作异步削峰异步下单。秒杀商品后就向消息队列发送一个下单消息,然后就直接返回给用户秒杀成功消息。订单服务会监听消息,当有消息后,订单服务就会执行下单流程。而秒杀服务根本不需要等待下单服务执行完成就可以返回秒杀的结果熔断降级可以保证系统不会直接瘫痪超卖问题使用redis信号量完成,让多个服务对库存的操作成原子性,不会造成多卖的情况支付超时采用延迟队列,下单成功后会在延迟队列也放入一个下单信息,如果超过指定的时间就通过死信交换机放进死信队列,当消费者进行消费的时候从该队列取出消息,判断超时后就进行退库操作网络开销

ES(ElasticSearch)

1、谈谈你对ElasticSearch的理解?

(简称ES)是基于Lucene全文搜索引擎的开源性搜索引擎,通过简单的 RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。ES即为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案,Elasticsearch是用Java开发的,但它却不是只支持Java语言,因为它支持RESTful方式调用,那理论上它是支持所有开发语言的,除此之外,如果你不想使用RESTful方式调用Elasticsearch服务器,那Elasticsearch还提供了各种语言的api供我们使用。

2、ES(ElasticSearch)优点

分布式存储方便集群性能高:实时搜索存储数量大处理PB级别数据基于Restful API 使用简单各种语言都支持使用它简单上手容易(因为使用retful风格):屏蔽了Lucene的复杂性

3、ES(ElasticSearch)相关概念

4.ElasticSearch__CRUD

1.添加PUT /索引库/类型/ID {json数据}2.获取GET /索引库/类型/ID3.删除DELETE /索引库/类型/ID4.修改全量PUT /索引库/类型/ID {json数据}增量修改POST /索引库/类型/ID/_update { doc:{json数据}}

5、ES(ElasticSearch)全文搜索的两个核心、

创建索引:为非结构化的数据创建索引搜索索引

6.ES(ElasticSearch)全文搜索创建索引大致原理

1.分词2.词态转换,大小写转换3.排序(自然顺序)4.合并单词(id倒排)5.形成倒排索引文档

6工作原理流程

倒排索引是什么?

传统的数据库我们检索是通过文章,逐个遍历找到对应关键词的位置。而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。倒排索引的底层实现是基于:FST(Finite State Transducer)数据结构。lucene 从 4+版本后开始大量使用的数据结构是 FST。FST 有两个优点:

1、空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;2、查询速度快。O(len(str))的查询时间复杂度。

7、ES(ElasticSearch)全文搜索哪些要建索引、要分词、不分词、哪些要存储到数据区?

存储数据到ElasticSearch时候需要创建索引库,有中文的时候就需要用插件分词器ik进行分词,

8、ES(ElasticSearch)查询条件?

match :标准查询(分词)match_allterm:单词查询(不分词,等值查询)range:范围查询prefix :前缀查询bool:组合多个条件wildcard:通配符查询

9、ElasticSearch使用的是query还是filter, 两者之间有什么区别

query查询过程:1,比较查询条件;2,然后计算分值,最后返回文档结果。这种查询方式适合于全文检索类的查询。filter查询过程1,判断是否满足查询条件,如果不满足,会缓存查询过程(记录该文档不满足结果);2,满足的话,就直接缓存结果。这种查询方式适合于精确值匹配方式的查询。综上所述,filter快在两个方面:1 对结果进行缓存;2 避免计算文档相关性分值。当我们不关心搜索结果的评分或者不使用全文检索的时候,为了提高性能,注意使用filter。

10、为什么不使用MySQL查询,而要用ES呢?

在一个电商平台项目中,会有非常多的商品,如果使用以往的MySQL进行模糊查询,需要比较长的等待时间,对数据库压力比较大,ES中使用倒排索引,查询效率非常高,可以减轻MySQL压力,而且还能进行分词查询和高亮处理,MySQL是做不到的。

不是所有的数据都会存在ES中,像商品规格表这种不常修改,且不会去模糊查询的放到缓存中就好了。

11、 Lucene和ES的区别

定义:Lucene是一个java信息检索程序库,一个jar包。您可以将其包含在项目中,并使用函数调用来参考其功能。Elasticsearch是基于JSON和Lucene的分布式Web服务。

关系:Elasticsearch基于Lucene构建,Elasticsearch利用Lucene做实际的工作ELasticsearch中的每个分片都是一个分离的Lucene实例.Elasticsearch在Lucene基础上(即利用Lucene的功能)提供了一个分布式的、基于JSON的REST API 来更方便地使用 Lucene的功能。Elasticsearch提供其他支持功能,如线程池,队列,节点/集群监控API,数据监控API,集群管理等

12、MySQL 数据如何同步到 ES 中

MySQL 数据同步到 ES 中,大致总结可以分为两种方案:

方案 1:监听 MySQL 的 Binlog,分析 Binlog 将数据同步到 ES 集群中。优点:业务与 ES 数据耦合度低,业务逻辑中不需要关心 ES 数据的写入;缺点:Binlog 模式只能使用 ROW 模式,且引入了新的同步服务,增加了开发量以及维护成本,也增大了 ES 同步的风险。方案 2:直接通过 ES的API 将数据写入到 ES 集群中。

优点:简洁明了,能够灵活的控制数据的写入;缺点:与业务耦合严重,强依赖于业务系统的写入方式。

考虑到订单系统 ES 服务的业务特殊性,对于订单数据的实时性较高,显然监听 Binlog 的方式相当于异步同步,有可能会产生较大的延时性。且方案 1 实质上跟方案 2 类似,但又引入了新的系统,维护成本也增高。所以订单中心 ES 采用了直接通过 ES API 写入订单数据的方式,该方式简洁灵活,能够很好的满足订单中心数据同步到 ES 的需求。

由于 ES 订单数据的同步采用的是在业务中写入的方式,当新建或更新文档发生异常时,如果重试势必会影响业务正常操作的响应时间。所以每次业务操作只更新一次 ES,如果发生错误或者异常,在数据库中插入一条补救任务,有定时工作任务队列会扫这些数据,以数据库订单数据为基准来再次更新 ES 数据。通过此种补偿机制,来保证 ES 数据与数据库订单数据的最终一致性。

13、在并发情况下,Elasticsearch 如果保证读写一致?

1、可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;

2、另外对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。

3、对于读操作,可以设置 replication 为 sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置 replication 为 async 时,也可以通过设置搜索请求参数_preference 为 primary 来查询主分片,确保文档是最新版本。

14、ElasticSearch的算法优化

这个问题问题的有点问题,使用elasticsearch不需要我们直接去优化算法,所有的优化都是通过配置完成。1分片的数量不少越多越好,因为查询结果是所有分片数据组装起来的,分片越多,消耗的IO越大,最好的是分片数等于节点数乘以3,比如有3个节点,那么索引的分片就创建9个。2默认情况下,一个分片对应着一个副本,副本可以起到负载均衡的效果,因为分片和副本都可以处理搜索的请求,所以适当的增加副本的数量,可以大大的提高系统的吞吐量,不过副本也会增加系统的压力,还会增加磁盘消耗,所以一般来说,设置2-3个副本就可以了。3设置线程池大小4尽量减少不需要的字段,这样可以节省一个文档所消耗的空间,在相同数据文档量的前提下,字段越少,搜索的速度越快5锁定内存,不让JVM写入swapping,避免降低ES的性能,对应的配置为bootstrap.mlockall: true6定时处理缓存,GET http://127.0.0.1:9200/*/_cache/clear定时合并优化资源,GET http://127.0.0.1:9200/*/_optimize

RabbitMQ

1、RabbitMQ 的使用场景有哪些?

削峰:消除峰值

异步化提速(发消息),提高系统稳定性(多系统调用),服务解耦(5-10个服务),排序保证,消除峰值

异步: 任务异步处理。将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。 提高了应用程序的响应时间,提高系统稳定性

解耦:应用程序解耦合 MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。· 抢购活动,削峰填谷,防止系统崩塌。· 延迟信息处理,比如 10 分钟之后给下单未付款的用户发送邮件提醒。· 解耦系统,对于新增的功能可以单独写模块扩展,比如用户确认评价之后,新增了给用户返积分的功能,这个时候不用在业务代码里添加新增积分的功能,只需要把新增积分的接口订阅确认评价的消息队列即可,后面再添加任何功能只需要订阅对应的消息队列即可。

1、rabbitMQ执行的原理:

生产者和消息队列建立连接——》创建通道——》 创建交换机 ——》交换机将消息分发不同的队列——》消费者和消息队列建立连接——》建立通道 ——》去对应的队列中获取消息

2、消息队列的基本模型

一、基本模型(一个生产者对应一个消费者)二、工作模型(一个生产者对应多个消费者)三、订阅模型——》交换机的类型:Fanout: 把消息发送给绑定交换机的所有队列Direct: 把消息发送给绑定交换机的所有队列中能匹配routingkey的队列.Topic: 把消息发送给绑定交换机的所有队列中能匹配routingkey的队列,绑定的时候可以使用通配符(# 匹配多个词, 匹配单个)

3、RabbitMQ什么情况下会出现消息丢失,如何解决

- ①、自动签收,消费失败 解决: -> 改为手动,在消费成功后再手动签收- ②、没有持久化,MQ进程挂掉,数据丢失 -> 持久化- ③、发送者消息投递失败 -> 投递回调(1.重试,2.日志记录,3.短信警报 4.发送消息持久到DB+定时任务重试,设置最大重试次数)

4、RabbitMQ如何防止重复消费消息 :幂等

什么是幂等性?

幂等性是指同一个操作无论请求多少次,其结果都相同。幂等操作实现方式有:1、操作之前在业务方法进行判断如果执行过了就不再执行。2、缓存所有请求和处理的结果,已经处理的请求则直接返回结果。3、在数据库表中加一个状态字段(未处理,已处理),数据操作时判断未处理时再处理。

幂等性:

产生原因:网络延迟传输中,会造成进行MQ重试中,在重试过程中,可能会造成重复消费。解决办法:很简单, 我们在生产者生产消息的时候, 都要给消息加一个messageId作为消息的唯一值, 就是为了消费方避免重复消费。

使用全局MessageID判断消费方使用同一个,解决幂等性。生产端设置消息ID消费端判断消息ID基于全局消息id区分消息,解决幂等性

5、RabbitMQ的交换机分为几类?有什么区别

Fanout: 分发模式、把消息发送给绑定交换机的所有队列direct(默认方式):把消息发送给绑定交换机的所有队列中能匹配routingkey的队列.默认采取轮询的方式进行消息发送。Topic: 把消息发送给绑定交换机的所有队列中能匹配routingkey的队列,绑定的时候可以使用通配符(# 匹配多个词, 匹配单个)Headers Exchanges:不处理路由键。而是根据发送的消息内容中的headers属性进行匹配,性能很差,此类型几乎用不到。

6、.SpringBoot整合MQ的大致步骤 导入依赖 spring-boot-starter-amqp- yml配置连接信息,手动签收,消费并发数,回调设置- 配置类:交换机,队列,绑定, RabbitTemplate配置JSON转换器,监听工厂配置JSON转换器,- 发送者:rabbitTemplate.converAndSend ,设置回调函数- 编写回调:发送者消息投递到交换机回到,交换机投递到队列回调- 消费者:通过监听标签,监听队列,方法处理消息,方法参数列表 ( @Payload 对象,通过,Message )

8、 RabbitMQ 有哪些重要的角色?

RabbitMQ 中重要的角色有:生产者、消费者和代理:· 生产者:消息的创建者,负责创建和推送数据到消息服务器;· 消费者:消息的接收方,用于处理数据和确认消息;· 代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

9. RabbitMQ 有哪些重要的组件?

· ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。· Channel(信道):消息推送使用的通道。· Exchange(交换器):用于接受、分配消息。· Queue(队列):用于存储生产者的消息。· RoutingKey(路由键):用于把生成者的数据分配到交换器上。· BindingKey(绑定键):用于把交换器的消息绑定到队列上。

10、 RabbitMQ要保证消息持久化成功的条件有哪些?

消息持久化:消息推送投递模式必须设置持久化,deliveryMode 设置为 2(持久)。交换机持久化:消息已经到达持久化交换器。队列持久化:消息已经到达持久化队列。声明队列必须设置持久化 durable 设置为 true.

11、RabbitMQ 怎么保证消息的稳定性?

· 提供了事务的功能。· 通过将 channel 设置为 confirm(确认)模式。

12、RabbitMQ 怎么避免消息丢失?

· 把消息持久化磁盘,保证服务器重启消息不丢失。· 每个集群中至少有一个物理磁盘,保证消息落入磁盘。

13、RabbitMQ 持久化有什么缺点?

持久化的缺地就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。可尽量使用 ssd 硬盘来缓解吞吐量的问题。

14. RabbitMQ 中 vhost 的作用是什么?

vhost:每个 RabbitMQ 都能创建很多 vhost,我们称之为虚拟主机,每个虚拟主机其实都是 mini 版的RabbitMQ,它拥有自己的队列,交换器和绑定,拥有自己的权限机制。

15、RabbitMQ 怎么实现延迟消息队列、使用场景?

延迟队列的实现有两种方式:①、通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;②、使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。使用场景1订单成功后,在30分钟内没有支付,自动取消订单2、外卖平台发送订餐通知,下单成功后60s给用户推送短信。3、如果订单一直处于某一个未完结状态时,及时处理关单,并退还库存4、淘宝新建商户一个月内还没上传商品信息,将冻结商铺等扩展(redis实现延迟队列)Redis 过期回调Redis 的key过期回调事件,也能达到延迟队列的效果,简单来说我们开启监听key是否过期的事件,一旦key过期会触发一个callback事件。修改redis.conf文件开启notify-keyspace-events Ex

16、RabbitMQ 集群有什么用?

集群主要有以下两个用途:高可用:某个服务器出现问题,整个 RabbitMQ 还可以继续使用;高容量:集群可以承载更多的消息量。

17、 RabbitMQ 节点的类型有哪些?

磁盘节点:消息会存储到磁盘。内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。

18、RabbitMQ 集群搭建需要注意哪些问题?

各节点之间使用“—link”连接,此属性不能忽略。各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。整个集群中必须包含一个磁盘节点。

19、RabbitMQ 每个节点是其他节点的完整拷贝吗?为什么?

不是,原因有以下两个:存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。

20、RabbitMQ 集群中唯一一个磁盘节点崩溃了会发生什么情况?

如果唯一磁盘的磁盘节点崩溃了,不能进行以下操作:不能创建队列不能创建交换器不能创建绑定不能添加用户不能更改权限不能添加和删除集群节点唯一磁盘节点崩溃了,集群是可以保持运行的,但你不能更改任何东西。

21、 RabbitMQ 对集群节点停止顺序有要求吗?

RabbitMQ 对集群的停止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。如果顺序恰好相反的话,可能会造成消息的丢失。

Zookeeper

1. zookeeper 是什么?

zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 google chubby 的开源实现,是 hadoop 和 hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

2.Zookeeper实现分布式锁的原理?

方案1 临时节点+重试

方案2 临时顺序节点+watch(下一个监听上一个)zookeeper实现分布式锁采用其提供的有序临时节点+监听来实现。临时节点只要客户端断开连接就会被删除,正好可以利用这一特性实现锁。

3. zookeeper 都有哪些功能?

· 集群管理:监控节点存活状态、运行请求等。· 主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 可以协助完成这个过程。· 分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。· 命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。

4. zookeeper 有几种部署模式?

zookeeper 有三种部署模式:· 单机部署:一台集群上运行;· 集群部署:多台集群运行;· 伪集群部署:一台集群启动多个 zookeeper 实例运行。

5. zookeeper 怎么保证主从节点的状态同步?

zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 zab 协议。 zab 协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。

6. 集群中为什么要有主节点?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,所以就需要主节点。

7. 集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗?

可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用。

8. 说一下 zookeeper 的通知机制?

客户端端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,然后客户端可以根据 znode 变化来做出业务上的改变。

JVM

1. 说一下 JVM 的主要组成部分?及其作用?

· 类加载器(ClassLoader)· 运行时数据区(Runtime Data Area)· 执行引擎(Execution Engine)· 本地库接口(Native Interface)组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

2. 说一下 JVM 运行时数据区?

不同虚拟机的运行时数据区可能略微有所不同,但都会遵从 Java 虚拟机规范, Java 虚拟机规范规定的区域分为以下 5 个部分:1. 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;2. Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;3. 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;4. Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;5. 方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

3. 说一下堆栈的区别?

· 功能方面:堆是用来存放对象的,栈是用来执行程序的。· 共享性:堆是线程共享的,栈是线程私有的。· 空间大小:堆大小远远大于栈。

4. 队列和栈是什么?有什么区别?

队列和栈都是被用来预存储数据的。队列允许先进先出检索元素,但也有例外的情况,Deque 接口允许从两端检索元素。栈和队列很相似,但它运行对元素进行后进先出进行检索。

5. 什么是双亲委派模型?

在介绍双亲委派模型之前先说下类加载器。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立在 JVM 中的唯一性,每一个类加载器,都有一个独立的类名称空间。类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转化为 class 对象。类加载器分类:· 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载Java_HOME/lib/目录中的,或者被 -Xbootclasspath 参数所指定的路径中并且被虚拟机识别的类库;· 其他类加载器:· 扩展类加载器(Extension ClassLoader):负责加载\lib\ext目录或Java. ext. dirs系统变量指定的路径中的所有类库;· 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。

6. 说一下类装载的执行过程?

类装载分为以下 5 个步骤:· 加载:根据查找路径找到相应的 class 文件然后导入;· 检查:检查加载的 class 文件的正确性;· 准备:给类中的静态变量分配内存空间;· 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;· 初始化:对静态变量和静态代码块执行初始化工作。

7. 怎么判断对象是否可以被回收?

一般有两种方法来判断:· 引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;· 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

8. Java 中都有哪些引用类型?

· 强引用:发生 gc 的时候不会被回收。· 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。· 弱引用:有用但不是必须的对象,在下一次GC时会被回收。· 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

9. 说一下 JVM 有哪些垃圾回收算法?

· 标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。· 标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。· 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。· 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

10. 说一下 JVM 有哪些垃圾回收器?

· Serial:最早的单线程串行垃圾回收器。· Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。· ParNew:是 Serial 的多线程版本。· Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。· Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。· CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。· G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。

11. 详细介绍一下 CMS 垃圾回收器?

CMS 是英文 Concurrent Mark-Sweep 的简称,是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。CMS 使用的是标记-清除的算法实现的,所以在 gc 的时候回产生大量的内存碎片,当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old 回收器进行垃圾清除,此时的性能将会被降低。

12. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

· 新生代回收器:Serial、ParNew、Parallel Scavenge· 老年代回收器:Serial Old、Parallel Old、CMS· 整堆回收器:G1新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低;老年代回收器一般采用的是标记-整理的算法进行垃圾回收。

13. 简述分代垃圾回收器是怎么工作的?

分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:· 把 Eden + From Survivor 存活的对象放入 To Survivor 区;· 清空 Eden 和 From Survivor 分区;· From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。

14. 说一下 JVM 调优的工具?

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。· jconsole:用于对 JVM 中的内存、线程和类等进行监控;· jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

15. 常用的 JVM 调优的参数都有哪些?

· -Xms2g:初始化推大小为 2g;· -Xmx2g:堆最大内存为 2g;· -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;· -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;· –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;· -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;· -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;· -XX:+PrintGC:开启打印 gc 信息;· -XX:+PrintGCDetails:打印 gc 详细信息。

.哪些因素可能会造成数据库性能问题?2.Mysql的执行流程是怎么样的?3.优化SQL你采用什么样的优化流程?4.如何去定位慢SQL根据慢日志5.定位到慢SQL你如何优化?Select前面加explain6.你如何看SQL有没有命中索引?7.mysql存储引擎有哪些,有什么区别,如何选择?8.一个sql : select sum(amount) from recharge ,来查询总充值,recharge 表数据量达到了上千万,怎么优化?9.什么是索引?10.Mysql索引有哪些类型?11.Mysql的索引原理?为什么用B+tree13.InnoDB的索引结构和MyIsam的索引结构有什么区别14.哪些列不适合创建索引15.哪些因素会造成索引失效16.InnoDB辅助索引的叶子节点也存数据吗?17.组合索引的匹配原则18.什么是Mysql主从复制,19.Mysql主从复制原理是怎么样的?20.简单说一下如何实现Mysql主从?Es添加文档原理:第一步:客户写集群某节点写入数据,发送请求。(如果没有指定路由/协调节点,请求的节点扮演路由节点的角色。)第二步:节点1接受到请求后,使用文档_id来确定文档属于分片0。请求会被转到另外的节点,假定节点3。因此分片0的主分片分配到节点3上。第三步:节点3在主分片上执行写操作,如果成功,则将请求并行转发到节点1和节点2的副本分片上,等待结果返回。所有的副本分片都报告成功,节点3将向协调节点(节点1)报告成功,节点1向请求客户端报告写入成功。如果面试官再问:第二步中的文档获取分片的过程?回答:借助路由算法获取,路由算法就是根据路由和文档id计算目标的分片id的过程。shard = hash(_routing) % (num_of_primary_shards)Redis中String底层用的SDS

高并发高并发的处理指标:响应时间,吞吐量,每秒查询率,并发用户数



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有